diff --git a/doc/OverlayTutorial.md b/doc/OverlayTutorial.md index ddd4edeb..97fd0ad4 100644 --- a/doc/OverlayTutorial.md +++ b/doc/OverlayTutorial.md @@ -104,7 +104,7 @@ class MyMessage(val message: String) : Serializable { return message.toByteArray() } - companion object : Deserializable { + companion object Deserializer : Deserializable { override fun deserialize(buffer: ByteArray, offset: Int): Pair { return Pair(MyMessage(buffer.toString(Charsets.UTF_8)), buffer.size) } @@ -119,7 +119,7 @@ private const val MESSAGE_ID = 1 fun broadcastGreeting() { for (peer in getPeers()) { - val packet = serializePacket(MESSAGE_ID, listOf(MyMessage("Hello!"))) + val packet = serializePacket(MESSAGE_ID, MyMessage("Hello!")) send(peer.address, packet) } } @@ -135,12 +135,12 @@ init { } private fun onMessage(packet: Packet) { - val (peer, payload) = packet.getAuthPayload(MyMessage.Companion, cryptoProvider) + val (peer, payload) = packet.getAuthPayload(MyMessage.Deserializer) Log.d("DemoCommunity", peer.mid + ": " + payload.message) } ``` -We can call `broadcastGreeting` function in our application e.g. in response to a button click, or we can add the following to our `Activity` to make sure we greet everyone every second even without user interaction: +We can call `broadcastGreeting` function in our application e.g. in response to a button click, or we can add a loop to our `Activity` to make sure we greet everyone every second even without user interaction: ```kotlin val community = IPv8Android.getInstance().getOverlay()!! diff --git a/ipv8-android/src/main/java/nl/tudelft/ipv8/android/IPv8Android.kt b/ipv8-android/src/main/java/nl/tudelft/ipv8/android/IPv8Android.kt index d8ae1404..020cd3bc 100644 --- a/ipv8-android/src/main/java/nl/tudelft/ipv8/android/IPv8Android.kt +++ b/ipv8-android/src/main/java/nl/tudelft/ipv8/android/IPv8Android.kt @@ -13,6 +13,7 @@ import nl.tudelft.ipv8.android.messaging.udp.AndroidUdpEndpoint import nl.tudelft.ipv8.android.service.IPv8Service import nl.tudelft.ipv8.keyvault.CryptoProvider import nl.tudelft.ipv8.keyvault.PrivateKey +import nl.tudelft.ipv8.keyvault.defaultCryptoProvider import java.net.InetAddress object IPv8Android { @@ -56,6 +57,8 @@ object IPv8Android { IPv8Android.ipv8 = ipv8 IPv8Android.serviceClass = serviceClass + defaultCryptoProvider = AndroidCryptoProvider + return ipv8 } diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/Community.kt b/ipv8/src/main/java/nl/tudelft/ipv8/Community.kt index 2175924f..b0125b27 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/Community.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/Community.kt @@ -38,10 +38,10 @@ abstract class Community : Overlay { protected lateinit var scope: CoroutineScope init { - messageHandlers[MessageId.PUNCTURE_REQUEST] = ::handlePunctureRequest - messageHandlers[MessageId.PUNCTURE] = ::handlePuncture - messageHandlers[MessageId.INTRODUCTION_REQUEST] = ::handleIntroductionRequest - messageHandlers[MessageId.INTRODUCTION_RESPONSE] = ::handleIntroductionResponse + messageHandlers[MessageId.PUNCTURE_REQUEST] = ::onPunctureRequestPacket + messageHandlers[MessageId.PUNCTURE] = ::onPuncturePacket + messageHandlers[MessageId.INTRODUCTION_REQUEST] = ::onIntroductionRequestPacket + messageHandlers[MessageId.INTRODUCTION_RESPONSE] = ::onIntroductionResponsePacket } override fun load() { @@ -167,12 +167,10 @@ abstract class Community : Overlay { ConnectionType.UNKNOWN, (globalTime % 65536u).toInt() ) - val auth = BinMemberAuthenticationPayload(myPeer.publicKey.keyToBin()) - val dist = GlobalTimeDistributionPayload(globalTime) logger.debug("-> $payload") - return serializePacket(MessageId.INTRODUCTION_REQUEST, listOf(auth, dist, payload)) + return serializePacket(MessageId.INTRODUCTION_REQUEST, payload) } internal fun createIntroductionResponse( @@ -180,24 +178,11 @@ abstract class Community : Overlay { socketAddress: Address, identifier: Int ): ByteArray { - val globalTime = claimGlobalTime() - var introductionLan = Address.EMPTY - var introductionWan = Address.EMPTY val other = network.getVerifiedByAddress(socketAddress) val intro = getPeerForIntroduction(exclude = other) - if (intro != null) { - /* - * If we are introducting a peer on our LAN, we assume our WAN is same as their WAN, - * and use their LAN port as a WAN port. Note that this will only work if the port is - * not translated by NAT. - */ - if (addressIsLan(intro.address)) { - introductionLan = intro.address - introductionWan = Address(myEstimatedWan.ip, introductionLan.port) - } else { - introductionWan = intro.address - } - } + val introductionLan = intro?.lanAddress ?: Address.EMPTY + val introductionWan = intro?.wanAddress ?: Address.EMPTY + val payload = IntroductionResponsePayload( socketAddress, myEstimatedLan, @@ -208,8 +193,6 @@ abstract class Community : Overlay { false, identifier ) - val auth = BinMemberAuthenticationPayload(myPeer.publicKey.keyToBin()) - val dist = GlobalTimeDistributionPayload(globalTime) if (intro != null) { // TODO: Seems like a bad practice to send a packet in the create method... @@ -221,38 +204,60 @@ abstract class Community : Overlay { logger.debug("-> $payload") - return serializePacket(MessageId.INTRODUCTION_RESPONSE, listOf(auth, dist, payload)) + return serializePacket(MessageId.INTRODUCTION_RESPONSE, payload) } internal fun createPuncture(lanWalker: Address, wanWalker: Address, identifier: Int): ByteArray { - val globalTime = claimGlobalTime() val payload = PuncturePayload(lanWalker, wanWalker, identifier) - val auth = BinMemberAuthenticationPayload(myPeer.publicKey.keyToBin()) - val dist = GlobalTimeDistributionPayload(globalTime) logger.debug("-> $payload") - return serializePacket(MessageId.PUNCTURE, listOf(auth, dist, payload)) + return serializePacket(MessageId.PUNCTURE, payload) } internal fun createPunctureRequest(lanWalker: Address, wanWalker: Address, identifier: Int): ByteArray { logger.debug("-> punctureRequest") - val globalTime = claimGlobalTime() val payload = PunctureRequestPayload(lanWalker, wanWalker, identifier) - val dist = GlobalTimeDistributionPayload(globalTime) - return serializePacket(MessageId.PUNCTURE_REQUEST, listOf(dist, payload), sign = false) + return serializePacket(MessageId.PUNCTURE_REQUEST, payload, sign = false) + } + + /** + * Serializes a payload into a binary packet that can be sent over the transport. + * + * @param messageId The message type ID + * @param payload The serializable payload + * @param sign True if the packet should be signed + * @param peer The peer that should sign the packet. The community's [myPeer] is used by default. + */ + protected fun serializePacket( + messageId: Int, + payload: Serializable, + sign: Boolean = true, + peer: Peer = myPeer + ): ByteArray { + val payloads = mutableListOf() + if (sign) { + payloads += BinMemberAuthenticationPayload(peer.publicKey.keyToBin()) + } + payloads += GlobalTimeDistributionPayload(claimGlobalTime()) + payloads += payload + return serializePacket( + messageId, + payloads, + sign, + peer + ) } /** * Serializes multiple payloads into a binary packet that can be sent over the transport. * - * @param prefix The packet prefix consisting of a zero byte, version, and master peer mid * @param messageId The message type ID * @param payload The list of payloads * @param sign True if the packet should be signed * @param peer The peer that should sign the packet. The community's [myPeer] is used by default. */ - protected fun serializePacket( + private fun serializePacket( messageId: Int, payload: List, sign: Boolean = true, @@ -277,37 +282,26 @@ abstract class Community : Overlay { * Request deserialization */ - internal fun deserializeIntroductionRequest(packet: Packet): Triple { - val (peer, remainder) = packet.getAuthPayload(cryptoProvider) - val (dist, distSize) = GlobalTimeDistributionPayload.deserialize(remainder) - val (payload, _) = IntroductionRequestPayload.deserialize(remainder, distSize) - return Triple(peer, dist, payload) + internal fun onIntroductionRequestPacket(packet: Packet) { + val (peer, payload) = + packet.getAuthPayload(IntroductionRequestPayload.Deserializer) + onIntroductionRequest(peer, payload) } - private fun handleIntroductionRequest(packet: Packet) { - val (peer, dist, payload) = deserializeIntroductionRequest(packet) - onIntroductionRequest(peer, dist, payload) + internal fun onIntroductionResponsePacket(packet: Packet) { + val (peer, payload) = + packet.getAuthPayload(IntroductionResponsePayload.Deserializer) + onIntroductionResponse(peer, payload) } - internal fun handleIntroductionResponse(packet: Packet) { - val (peer, remainder) = packet.getAuthPayload(cryptoProvider) - val (dist, distSize) = GlobalTimeDistributionPayload.deserialize(remainder) - val (payload, _) = IntroductionResponsePayload.deserialize(remainder, distSize) - onIntroductionResponse(peer, dist, payload) + internal fun onPuncturePacket(packet: Packet) { + val (peer, payload) = packet.getAuthPayload(PuncturePayload.Deserializer) + onPuncture(peer, payload) } - internal fun handlePuncture(packet: Packet) { - val (peer, remainder) = packet.getAuthPayload(cryptoProvider) - val (dist, distSize) = GlobalTimeDistributionPayload.deserialize(remainder) - val (payload, _) = PuncturePayload.deserialize(remainder, distSize) - onPuncture(peer, dist, payload) - } - - internal fun handlePunctureRequest(packet: Packet) { - val remainder = packet.getPayload() - val (dist, distSize) = GlobalTimeDistributionPayload.deserialize(remainder) - val (payload, _) = PunctureRequestPayload.deserialize(remainder, distSize) - onPunctureRequest(packet.source, dist, payload) + internal fun onPunctureRequestPacket(packet: Packet) { + val payload = packet.getPayload(PunctureRequestPayload.Deserializer) + onPunctureRequest(packet.source, payload) } /* @@ -316,7 +310,6 @@ abstract class Community : Overlay { internal open fun onIntroductionRequest( peer: Peer, - dist: GlobalTimeDistributionPayload, payload: IntroductionRequestPayload ) { logger.debug("<- $payload") @@ -326,8 +319,8 @@ abstract class Community : Overlay { return } - network.addVerifiedPeer(peer) - network.discoverServices(peer, listOf(serviceId)) + // Add the sender as a verified peer + addVerifiedPeer(peer, payload.sourceLanAddress, payload.sourceWanAddress) val packet = createIntroductionResponse( payload.sourceLanAddress, @@ -340,39 +333,60 @@ abstract class Community : Overlay { open fun onIntroductionResponse( peer: Peer, - dist: GlobalTimeDistributionPayload, payload: IntroductionResponsePayload ) { logger.debug("<- $payload") - // Accept a new WAN address if the sender is not on the same LAN, otherwise they would - // just send us our LAN address - if (payload.sourceWanAddress.ip != myEstimatedWan.ip) { + // Change our estimated WAN address if the sender is not on the same LAN, otherwise it + // would just send us our LAN address + if (!addressIsLan(peer.address)) { myEstimatedWan = payload.destinationAddress } - network.addVerifiedPeer(peer) - network.discoverServices(peer, listOf(serviceId)) + // Add the sender as a verified peer + addVerifiedPeer(peer, payload.sourceLanAddress, payload.sourceWanAddress) + // Process introduced addresses if (!payload.wanIntroductionAddress.isEmpty() && payload.wanIntroductionAddress.ip != myEstimatedWan.ip) { - // WAN is not empty and it is not the same as ours + // WAN is not empty and it is not same as ours + if (!payload.lanIntroductionAddress.isEmpty()) { // If LAN address is not empty, add them in case they are on our LAN discoverAddress(peer, payload.lanIntroductionAddress, serviceId) } + + // Discover WAN address. We should contact it ASAP as it just received a puncture + // request and probably already sent a puncture to us. discoverAddress(peer, payload.wanIntroductionAddress, serviceId) } else if (!payload.lanIntroductionAddress.isEmpty() && payload.wanIntroductionAddress.ip == myEstimatedWan.ip) { // LAN is not empty and WAN is the same as ours => they are on the same LAN discoverAddress(peer, payload.lanIntroductionAddress, serviceId) } else if (!payload.wanIntroductionAddress.isEmpty()) { - // WAN is the same as ours, but we do not know the LAN => we assume LAN is the same as ours + // WAN is same as ours, but we do not know the LAN + + // Try to connect via WAN, NAT needs to support hairpinning discoverAddress(peer, payload.wanIntroductionAddress, serviceId) - discoverAddress(peer, Address(myEstimatedLan.ip, payload.wanIntroductionAddress.port), serviceId) + + // Assume LAN is same as ours (e.g. multiple instances running on a local machine), + // and port same as for WAN (works only if NAT does not change port) + discoverAddress(peer, Address(myEstimatedLan.ip, payload.wanIntroductionAddress.port), + serviceId) } } + private fun addVerifiedPeer(peer: Peer, sourceLanAddress: Address, sourceWanAddress: Address) { + val newPeer = Peer( + peer.key, + peer.address, + lanAddress = sourceLanAddress, + wanAddress = sourceWanAddress + ) + network.addVerifiedPeer(newPeer) + network.discoverServices(newPeer, listOf(serviceId)) + } + protected open fun discoverAddress(peer: Peer, address: Address, serviceId: String) { // Prevent discovering its own address if (address != myEstimatedLan && address != myEstimatedWan) { @@ -382,7 +396,6 @@ abstract class Community : Overlay { internal open fun onPuncture( peer: Peer, - dist: GlobalTimeDistributionPayload, payload: PuncturePayload ) { logger.debug("<- $payload") @@ -391,7 +404,6 @@ abstract class Community : Overlay { internal open fun onPunctureRequest( address: Address, - dist: GlobalTimeDistributionPayload, payload: PunctureRequestPayload ) { logger.debug("<- $payload") diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/Peer.kt b/ipv8/src/main/java/nl/tudelft/ipv8/Peer.kt index dc940f57..ae139dae 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/Peer.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/Peer.kt @@ -12,10 +12,20 @@ data class Peer( val key: Key, /** - * The address of this peer. + * The address of this peer it contacted us from (can be LAN or WAN). */ var address: Address = Address.EMPTY, + /** + * The LAN address of this peer. + */ + var lanAddress: Address = Address.EMPTY, + + /** + * The WAN address of this peer. + */ + var wanAddress: Address = Address.EMPTY, + /** * Is this peer suggested to us (otherwise it contacted us). */ diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainBlock.kt b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainBlock.kt index e8d20fad..06fdd7fd 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainBlock.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainBlock.kt @@ -2,12 +2,13 @@ package nl.tudelft.ipv8.attestation.trustchain import nl.tudelft.ipv8.attestation.trustchain.payload.HalfBlockPayload import nl.tudelft.ipv8.attestation.trustchain.store.TrustChainStore +import nl.tudelft.ipv8.attestation.trustchain.validation.ValidationErrors import nl.tudelft.ipv8.attestation.trustchain.validation.ValidationResult -import nl.tudelft.ipv8.keyvault.PrivateKey +import nl.tudelft.ipv8.keyvault.* import nl.tudelft.ipv8.util.sha256 import nl.tudelft.ipv8.util.toHex -import java.lang.Exception import java.util.* +import kotlin.Exception val GENESIS_HASH = ByteArray(32) val GENESIS_SEQ = 1u @@ -122,6 +123,8 @@ class TrustChainBlock( * Validates this block against what is known in the database. */ fun validate(database: TrustChainStore): ValidationResult { + // val blk = database.get(publicKey, sequenceNumber) + // val link = database.getLinked(this) val prevBlk = database.getBlockBefore(this) val nextBlk = database.getBlockAfter(this) @@ -137,7 +140,8 @@ class TrustChainBlock( // TODO: Check if the linked block as retrieved from our database is the same as the one // linked by this block. Detect double countersign fraud. - // TODO: Check if the chain of blocks is properly hooked up. + // Check if the chain of blocks is properly hooked up. + result = validateChainConsistency(prevBlk, nextBlk, result) return result } @@ -176,17 +180,79 @@ class TrustChainBlock( val errors = mutableListOf() if (sequenceNumber < GENESIS_SEQ) { - errors += "Sequence number is prior to genesis" + errors += ValidationErrors.INVALID_SEQUENCE_NUMBER } - // TODO: Check signature + if (!defaultCryptoProvider.isValidPublicBin(publicKey)) { + errors += ValidationErrors.INVALID_PUBLIC_KEY + } + + if (!linkPublicKey.contentEquals(EMPTY_PK) && + !linkPublicKey.contentEquals(ANY_COUNTERPARTY_PK) && + !defaultCryptoProvider.isValidPublicBin(linkPublicKey)) { + errors += ValidationErrors.INVALID_LINK_PUBLIC_KEY + } + + try { + val pk = defaultCryptoProvider.keyFromPublicBin(publicKey) + val serialized = HalfBlockPayload.fromHalfBlock(this, false).serialize() + if (!pk.verify(signature, serialized)) { + errors += ValidationErrors.INVALID_SIGNATURE + } + } catch (e: Exception) { + e.printStackTrace() + } if (sequenceNumber == GENESIS_SEQ && !previousHash.contentEquals(GENESIS_HASH)) { - errors += "Sequence number implies previous hash should be Genesis ID" + errors += ValidationErrors.INVALID_GENESIS_HASH } if (sequenceNumber != GENESIS_SEQ && previousHash.contentEquals(GENESIS_HASH)) { - errors += "Sequence number implies previous hash should not be Genesis ID" + errors += ValidationErrors.INVALID_GENESIS_SEQUENCE_NUMBER + } + + return updateValidationResult(prevResult, errors) + } + + /** + * Check for chain order consistency. + * + * The previous block should point to us and this block should point to the next block. + */ + private fun validateChainConsistency( + prevBlk: TrustChainBlock?, + nextBlk: TrustChainBlock?, + prevResult: ValidationResult + ): ValidationResult { + val errors = mutableListOf() + + if (prevBlk != null) { + if (!prevBlk.publicKey.contentEquals(publicKey)) { + errors += ValidationErrors.PREVIOUS_PUBLIC_KEY_MISMATCH + } + if (prevBlk.sequenceNumber >= sequenceNumber) { + errors += ValidationErrors.PREVIOUS_SEQUENCE_NUMBER_MISMATCH + } + val isPrevGap = prevBlk.sequenceNumber != sequenceNumber - 1u + if (!isPrevGap && !prevBlk.calculateHash().contentEquals(previousHash)) { + errors += ValidationErrors.PREVIOUS_HASH_MISMATCH + // Is this fraud? It is certainly an error, but fixing it would require a different + // signature on the same sequence number which is fraud. + } + } + + if (nextBlk != null) { + if (!nextBlk.publicKey.contentEquals(publicKey)) { + errors += ValidationErrors.NEXT_PUBLIC_KEY_MISMATCH + } + if (nextBlk.sequenceNumber <= sequenceNumber) { + errors += ValidationErrors.NEXT_SEQUENCE_NUMBER_MISMATCH + } + val isNextGap = nextBlk.sequenceNumber != sequenceNumber + 1u + if (!isNextGap && !nextBlk.previousHash.contentEquals(calculateHash())) { + errors += ValidationErrors.NEXT_HASH_MISMATCH + // Again, this might not be fraud, but fixing it can only result in fraud. + } } return updateValidationResult(prevResult, errors) diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainCommunity.kt b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainCommunity.kt index ae535e40..f04a82cb 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainCommunity.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainCommunity.kt @@ -8,11 +8,10 @@ import nl.tudelft.ipv8.* import nl.tudelft.ipv8.attestation.trustchain.validation.TransactionValidator import nl.tudelft.ipv8.attestation.trustchain.validation.ValidationResult import nl.tudelft.ipv8.messaging.Packet -import nl.tudelft.ipv8.messaging.payload.GlobalTimeDistributionPayload import nl.tudelft.ipv8.util.random import nl.tudelft.ipv8.attestation.trustchain.payload.* import nl.tudelft.ipv8.attestation.trustchain.store.TrustChainStore -import nl.tudelft.ipv8.messaging.payload.BinMemberAuthenticationPayload +import nl.tudelft.ipv8.attestation.trustchain.validation.ValidationErrors import nl.tudelft.ipv8.util.toHex import java.util.* import kotlin.coroutines.Continuation @@ -134,21 +133,16 @@ open class TrustChainCommunity( * Send a block to a specific address, or do a broadcast to known peers if no peer is specified. */ fun sendBlock(block: TrustChainBlock, address: Address? = null, ttl: Int = 1) { - val globalTime = claimGlobalTime() - val dist = GlobalTimeDistributionPayload(globalTime) - if (address != null) { logger.debug("Sending block to $address") val payload = HalfBlockPayload.fromHalfBlock(block) logger.debug("-> $payload") - val packet = serializePacket(MessageId.HALF_BLOCK, listOf(dist, payload), - false) + val packet = serializePacket(MessageId.HALF_BLOCK, payload, false) send(address, packet) } else { val payload = HalfBlockBroadcastPayload.fromHalfBlock(block, ttl.toUInt()) logger.debug("-> $payload") - val packet = serializePacket(MessageId.HALF_BLOCK_BROADCAST, listOf(dist, - payload), false) + val packet = serializePacket(MessageId.HALF_BLOCK_BROADCAST, payload, false) val randomPeers = getPeers().random(settings.broadcastFanout) for (peer in randomPeers) { send(peer.address, packet) @@ -167,20 +161,16 @@ open class TrustChainCommunity( address: Address? = null, ttl: UInt = 1u ) { - val globalTime = claimGlobalTime() - val dist = GlobalTimeDistributionPayload(globalTime) - if (address != null) { val payload = HalfBlockPairPayload.fromHalfBlocks(block1, block2) logger.debug("-> $payload") - val packet = serializePacket(MessageId.HALF_BLOCK_PAIR, listOf(dist, payload), - false) + val packet = serializePacket(MessageId.HALF_BLOCK_PAIR, payload, false) send(address, packet) } else { val payload = HalfBlockPairBroadcastPayload.fromHalfBlocks(block1, block2, ttl) logger.debug("-> $payload") - val packet = serializePacket(MessageId.HALF_BLOCK_PAIR_BROADCAST, - listOf(dist, payload)) + val packet = serializePacket(MessageId.HALF_BLOCK_PAIR_BROADCAST, payload, + false) for (peer in network.getRandomPeers(settings.broadcastFanout)) { send(peer.address, packet) } @@ -296,12 +286,10 @@ open class TrustChainCommunity( val blocks = suspendCancellableCoroutine> { continuation -> crawlRequestCache[crawlId] = CrawlRequest(peer, continuation) - val auth = BinMemberAuthenticationPayload(myPeer.publicKey.keyToBin()) - val dist = GlobalTimeDistributionPayload(globalTime) val payload = CrawlRequestPayload(publicKey, range.first, range.last, crawlId) logger.debug("-> $payload") - val packet = serializePacket(MessageId.CRAWL_REQUEST, listOf(auth, dist, payload)) + val packet = serializePacket(MessageId.CRAWL_REQUEST, payload) endpoint.send(peer.address, packet) } @@ -318,37 +306,37 @@ open class TrustChainCommunity( */ private fun onHalfBlockPacket(packet: Packet) { - val payload = packet.getPayload(HalfBlockPayload.Companion) + val payload = packet.getPayload(HalfBlockPayload.Deserializer) onHalfBlock(packet.source, payload) } private fun onHalfBlockBroadcastPacket(packet: Packet) { - val payload = packet.getPayload(HalfBlockBroadcastPayload.Companion) + val payload = packet.getPayload(HalfBlockBroadcastPayload.Deserializer) onHalfBlockBroadcast(payload) } private fun onHalfBlockPairPacket(packet: Packet) { - val payload = packet.getPayload(HalfBlockPairPayload.Companion) + val payload = packet.getPayload(HalfBlockPairPayload.Deserializer) onHalfBlockPair(payload) } private fun onHalfBlockPairBroadcastPacket(packet: Packet) { - val payload = packet.getPayload(HalfBlockPairBroadcastPayload.Companion) + val payload = packet.getPayload(HalfBlockPairBroadcastPayload.Deserializer) onHalfBlockPairBroadcast(payload) } private fun onCrawlRequestPacket(packet: Packet) { - val (peer, payload) = packet.getAuthPayload(CrawlRequestPayload.Companion, cryptoProvider) + val (peer, payload) = packet.getAuthPayload(CrawlRequestPayload.Deserializer) onCrawlRequest(peer, payload) } private fun onCrawlResponsePacket(packet: Packet) { - val payload = packet.getPayload(CrawlResponsePayload.Companion) + val payload = packet.getPayload(CrawlResponsePayload.Deserializer) onCrawlResponse(packet.source, payload) } private fun onEmptyCrawlResponsePacket(packet: Packet) { - val payload = packet.getPayload(EmptyCrawlResponsePayload.Companion) + val payload = packet.getPayload(EmptyCrawlResponsePayload.Deserializer) onEmptyCrawlResponse(payload) } @@ -419,12 +407,10 @@ open class TrustChainCommunity( limit = settings.maxCrawlBatch) if (blocks.isEmpty()) { - val globalTime = claimGlobalTime() val responsePayload = EmptyCrawlResponsePayload(payload.crawlId) - val dist = GlobalTimeDistributionPayload(globalTime) logger.debug("-> $payload") val packet = serializePacket(MessageId.EMPTY_CRAWL_RESPONSE, - listOf(dist, responsePayload), false) + responsePayload, false) send(peer.address, packet) } else { sendCrawlResponses(blocks, peer, payload.crawlId) @@ -445,14 +431,11 @@ open class TrustChainCommunity( totalCount: Int, peer: Peer ) { - - val globalTime = claimGlobalTime() - val payload = CrawlResponsePayload.fromCrawl(block, crawlId, index.toUInt(), - totalCount.toUInt()) - val dist = GlobalTimeDistributionPayload(globalTime) + val payload = CrawlResponsePayload.fromCrawl(block, crawlId, + index.toUInt(), totalCount.toUInt()) logger.debug("-> $payload") - val packet = serializePacket(MessageId.CRAWL_RESPONSE, listOf(dist, payload), false) + val packet = serializePacket(MessageId.CRAWL_RESPONSE, payload, false) send(peer.address, packet) } @@ -568,7 +551,7 @@ open class TrustChainCommunity( val validator = getTransactionValidator(block.type) if (validator != null) { if (!validator.validate(block, database)) { - validationResult = ValidationResult.Invalid(listOf("Invalid transaction")) + validationResult = ValidationResult.Invalid(listOf(ValidationErrors.INVALID_TRANSACTION)) } } } diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/CrawlRequestPayload.kt b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/CrawlRequestPayload.kt index c78c688f..a13846c2 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/CrawlRequestPayload.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/CrawlRequestPayload.kt @@ -18,7 +18,7 @@ class CrawlRequestPayload( serializeUInt(crawlId) } - companion object : Deserializable { + companion object Deserializer : Deserializable { override fun deserialize(buffer: ByteArray, offset: Int): Pair { var localOffset = 0 val publicKey = buffer.copyOfRange(offset + localOffset, diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/CrawlResponsePayload.kt b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/CrawlResponsePayload.kt index 20518ac2..aa22c4a0 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/CrawlResponsePayload.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/CrawlResponsePayload.kt @@ -19,7 +19,7 @@ open class CrawlResponsePayload( serializeUInt(totalCount) } - companion object : Deserializable { + companion object Deserializer : Deserializable { override fun deserialize(buffer: ByteArray, offset: Int): Pair { var (block, localOffset) = HalfBlockPayload.deserialize(buffer, offset) val crawlId = deserializeUInt(buffer, offset + localOffset) diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/EmptyCrawlResponsePayload.kt b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/EmptyCrawlResponsePayload.kt index d3af7438..b73af95f 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/EmptyCrawlResponsePayload.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/EmptyCrawlResponsePayload.kt @@ -12,7 +12,7 @@ data class EmptyCrawlResponsePayload( return serializeUInt(crawlId) } - companion object : Deserializable { + companion object Deserializer : Deserializable { override fun deserialize( buffer: ByteArray, offset: Int diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/HalfBlockBroadcastPayload.kt b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/HalfBlockBroadcastPayload.kt index bd792112..ed72410b 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/HalfBlockBroadcastPayload.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/HalfBlockBroadcastPayload.kt @@ -14,7 +14,7 @@ class HalfBlockBroadcastPayload( return block.serialize() + serializeUInt(ttl) } - companion object : Deserializable { + companion object Deserializer : Deserializable { override fun deserialize(buffer: ByteArray, offset: Int): Pair { var (block, localOffset) = HalfBlockPayload.deserialize(buffer, offset) val ttl = deserializeUInt(buffer, offset + localOffset) diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/HalfBlockPairBroadcastPayload.kt b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/HalfBlockPairBroadcastPayload.kt index 0e5ed985..8b203c24 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/HalfBlockPairBroadcastPayload.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/HalfBlockPairBroadcastPayload.kt @@ -15,7 +15,7 @@ open class HalfBlockPairBroadcastPayload( return block1.serialize() + block2.serialize() + serializeUInt(ttl) } - companion object : Deserializable { + companion object Deserializer : Deserializable { override fun deserialize(buffer: ByteArray, offset: Int): Pair { val (block1, block1Size) = HalfBlockPayload.deserialize(buffer, offset) val (block2, block2Size) = HalfBlockPayload.deserialize(buffer, offset + block1Size) diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/HalfBlockPairPayload.kt b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/HalfBlockPairPayload.kt index c504b89f..7029f2bb 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/HalfBlockPairPayload.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/HalfBlockPairPayload.kt @@ -14,7 +14,7 @@ open class HalfBlockPairPayload( return block1.serialize() + block2.serialize() } - companion object : Deserializable { + companion object Deserializer : Deserializable { override fun deserialize(buffer: ByteArray, offset: Int): Pair { val (block1, block1Size) = HalfBlockPayload.deserialize(buffer, offset) val (block2, block2Size) = HalfBlockPayload.deserialize(buffer, offset + block1Size) diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/HalfBlockPayload.kt b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/HalfBlockPayload.kt index 494c1c96..b9854b8b 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/HalfBlockPayload.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/payload/HalfBlockPayload.kt @@ -46,7 +46,7 @@ open class HalfBlockPayload( ) } - companion object : Deserializable { + companion object Deserializer : Deserializable { override fun deserialize(buffer: ByteArray, offset: Int): Pair { var localOffset = 0 val publicKey = buffer.copyOfRange(offset + localOffset, offset + localOffset + SERIALIZED_PUBLIC_KEY_SIZE) diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/validation/ValidationResult.kt b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/validation/ValidationResult.kt index 498707b4..99ae6cba 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/validation/ValidationResult.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/attestation/trustchain/validation/ValidationResult.kt @@ -38,3 +38,19 @@ sealed class ValidationResult { } } } + +object ValidationErrors { + const val INVALID_SEQUENCE_NUMBER = "INVALID_SEQUENCE_NUMBER" + const val INVALID_PUBLIC_KEY = "INVALID_PUBLIC_KEY" + const val INVALID_LINK_PUBLIC_KEY = "INVALID_LINK_PUBLIC_KEY" + const val INVALID_SIGNATURE = "INVALID_SIGNATURE" + const val INVALID_GENESIS_SEQUENCE_NUMBER = "INVALID_GENESIS_SEQUENCE_NUMBER" + const val INVALID_GENESIS_HASH = "INVALID_GENESIS_HASH" + const val INVALID_TRANSACTION = "INVALID_TRANSACTION" + const val PREVIOUS_PUBLIC_KEY_MISMATCH = "PREVIOUS_PUBLIC_KEY_MISMATCH" + const val PREVIOUS_SEQUENCE_NUMBER_MISMATCH = "PREVIOUS_SEQUENCE_NUMBER_MISMATCH" + const val PREVIOUS_HASH_MISMATCH = "PREVIOUS_HASH_MISMATCH" + const val NEXT_PUBLIC_KEY_MISMATCH = "NEXT_PUBLIC_KEY_MISMATCH" + const val NEXT_SEQUENCE_NUMBER_MISMATCH = "NEXT_SEQUENCE_NUMBER_MISMATCH" + const val NEXT_HASH_MISMATCH = "NEXT_HASH_MISMATCH" +} diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/keyvault/CryptoProvider.kt b/ipv8/src/main/java/nl/tudelft/ipv8/keyvault/CryptoProvider.kt index 9109046c..831676a6 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/keyvault/CryptoProvider.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/keyvault/CryptoProvider.kt @@ -4,4 +4,14 @@ interface CryptoProvider { fun generateKey(): PrivateKey fun keyFromPublicBin(bin: ByteArray): PublicKey fun keyFromPrivateBin(bin: ByteArray): PrivateKey + fun isValidPublicBin(bin: ByteArray): Boolean { + return try { + keyFromPublicBin(bin) + true + } catch (e: Exception) { + false + } + } } + +var defaultCryptoProvider: CryptoProvider = JavaCryptoProvider diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/messaging/Packet.kt b/ipv8/src/main/java/nl/tudelft/ipv8/messaging/Packet.kt index fd003c32..0c214794 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/messaging/Packet.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/messaging/Packet.kt @@ -3,7 +3,7 @@ package nl.tudelft.ipv8.messaging import nl.tudelft.ipv8.Address import nl.tudelft.ipv8.Peer import nl.tudelft.ipv8.exception.PacketDecodingException -import nl.tudelft.ipv8.keyvault.CryptoProvider +import nl.tudelft.ipv8.keyvault.defaultCryptoProvider import nl.tudelft.ipv8.messaging.payload.BinMemberAuthenticationPayload import nl.tudelft.ipv8.messaging.payload.GlobalTimeDistributionPayload @@ -28,9 +28,9 @@ class Packet( * * @throws PacketDecodingException If the packet is authenticated and the signature is invalid. */ - fun getAuthPayload(deserializer: Deserializable, cryptoProvider: CryptoProvider): - Pair { - val (peer, remainder) = getAuthPayload(cryptoProvider) + @Throws(PacketDecodingException::class) + fun getAuthPayload(deserializer: Deserializable): Pair { + val (peer, remainder) = getAuthPayload() val (_, distSize) = GlobalTimeDistributionPayload.deserialize(remainder) val (payload, _) = deserializer.deserialize(remainder, distSize) return Pair(peer, payload) @@ -39,7 +39,7 @@ class Packet( /** * Strips the prefix, message type, and returns the raw payload. */ - fun getPayload(): ByteArray { + private fun getPayload(): ByteArray { return data.copyOfRange(PREFIX_SIZE + 1, data.size) } @@ -52,11 +52,11 @@ class Packet( * @throws PacketDecodingException If the packet is authenticated and the signature is invalid. */ @Throws(PacketDecodingException::class) - fun getAuthPayload(cryptoProvider: CryptoProvider): Pair { + private fun getAuthPayload(): Pair { // prefix + message type val authOffset = PREFIX_SIZE + 1 val (auth, authSize) = BinMemberAuthenticationPayload.deserialize(data, authOffset) - val publicKey = cryptoProvider.keyFromPublicBin(auth.publicKey) + val publicKey = defaultCryptoProvider.keyFromPublicBin(auth.publicKey) val signatureOffset = data.size - publicKey.getSignatureLength() val signature = data.copyOfRange(signatureOffset, data.size) diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/messaging/payload/IntroductionRequestPayload.kt b/ipv8/src/main/java/nl/tudelft/ipv8/messaging/payload/IntroductionRequestPayload.kt index 50d7e118..14228358 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/messaging/payload/IntroductionRequestPayload.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/messaging/payload/IntroductionRequestPayload.kt @@ -49,7 +49,7 @@ data class IntroductionRequestPayload( serializeUShort(identifier) } - companion object : Deserializable { + companion object Deserializer : Deserializable { override fun deserialize(buffer: ByteArray, offset: Int): Pair { var localOffset = 0 val (destinationAddress, _) = Address.deserialize(buffer, offset + localOffset) diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/messaging/payload/IntroductionResponsePayload.kt b/ipv8/src/main/java/nl/tudelft/ipv8/messaging/payload/IntroductionResponsePayload.kt index ee794de6..df660246 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/messaging/payload/IntroductionResponsePayload.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/messaging/payload/IntroductionResponsePayload.kt @@ -69,7 +69,7 @@ data class IntroductionResponsePayload( serializeUShort(identifier) } - companion object : Deserializable { + companion object Deserializer : Deserializable { override fun deserialize(buffer: ByteArray, offset: Int): Pair { var localOffset = 0 val (destinationAddress, _) = Address.deserialize(buffer, offset + localOffset) diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/messaging/payload/PuncturePayload.kt b/ipv8/src/main/java/nl/tudelft/ipv8/messaging/payload/PuncturePayload.kt index f7473ead..0cb6e18c 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/messaging/payload/PuncturePayload.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/messaging/payload/PuncturePayload.kt @@ -30,7 +30,7 @@ data class PuncturePayload( serializeUShort(identifier) } - companion object : Deserializable { + companion object Deserializer : Deserializable { override fun deserialize(buffer: ByteArray, offset: Int): Pair { var localOffset = 0 val (sourceLanAddress, _) = Address.deserialize(buffer, offset + localOffset) diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/messaging/payload/PunctureRequestPayload.kt b/ipv8/src/main/java/nl/tudelft/ipv8/messaging/payload/PunctureRequestPayload.kt index b61543b4..f9120edc 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/messaging/payload/PunctureRequestPayload.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/messaging/payload/PunctureRequestPayload.kt @@ -31,7 +31,7 @@ data class PunctureRequestPayload( serializeUShort(identifier) } - companion object : Deserializable { + companion object Deserializer : Deserializable { override fun deserialize(buffer: ByteArray, offset: Int): Pair { var localOffset = 0 val (lanWalkerAddress, _) = Address.deserialize(buffer, offset + localOffset) diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/DiscoveryCommunity.kt b/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/DiscoveryCommunity.kt index 5772703b..8e92484a 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/DiscoveryCommunity.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/DiscoveryCommunity.kt @@ -21,10 +21,10 @@ class DiscoveryCommunity : Community(), PingOverlay { private val pingRequestCache: MutableMap = mutableMapOf() init { - messageHandlers[MessageId.SIMILARITY_REQUEST] = ::handleSimilarityRequest - messageHandlers[MessageId.SIMILARITY_RESPONSE] = ::handleSimilarityResponse - messageHandlers[MessageId.PING] = ::handlePing - messageHandlers[MessageId.PONG] = ::handlePong + messageHandlers[MessageId.SIMILARITY_REQUEST] = ::onSimilarityRequestPacket + messageHandlers[MessageId.SIMILARITY_RESPONSE] = ::onSimilarityResponsePacket + messageHandlers[MessageId.PING] = ::onPingPacket + messageHandlers[MessageId.PONG] = ::onPongPacket } /* @@ -40,10 +40,8 @@ class DiscoveryCommunity : Community(), PingOverlay { ConnectionType.UNKNOWN, getMyOverlays(peer) ) - val auth = BinMemberAuthenticationPayload(peer.publicKey.keyToBin()) - val dist = GlobalTimeDistributionPayload(globalTime) logger.debug("-> $payload") - return serializePacket(MessageId.SIMILARITY_REQUEST, listOf(auth, dist, payload), peer = peer) + return serializePacket(MessageId.SIMILARITY_REQUEST, payload, peer = peer) } fun sendSimilarityRequest(address: Address) { @@ -55,20 +53,16 @@ class DiscoveryCommunity : Community(), PingOverlay { } internal fun createSimilarityResponse(identifier: Int, peer: Peer): ByteArray { - val globalTime = claimGlobalTime() val payload = SimilarityResponsePayload(identifier, getMyOverlays(peer)) - val auth = BinMemberAuthenticationPayload(peer.publicKey.keyToBin()) - val dist = GlobalTimeDistributionPayload(globalTime) logger.debug("-> $payload") - return serializePacket(MessageId.SIMILARITY_RESPONSE, listOf(auth, dist, payload), peer = peer) + return serializePacket(MessageId.SIMILARITY_RESPONSE, payload, peer = peer) } internal fun createPing(): Pair { val globalTime = claimGlobalTime() val payload = PingPayload((globalTime % 65536u).toInt()) - val dist = GlobalTimeDistributionPayload(globalTime) logger.debug("-> $payload") - return Pair(payload.identifier, serializePacket(MessageId.PING, listOf(dist, payload), sign = false)) + return Pair(payload.identifier, serializePacket(MessageId.PING, payload, sign = false)) } override fun sendPing(peer: Peer) { @@ -82,43 +76,35 @@ class DiscoveryCommunity : Community(), PingOverlay { } internal fun createPong(identifier: Int): ByteArray { - val globalTime = claimGlobalTime() val payload = PongPayload(identifier) - val dist = GlobalTimeDistributionPayload(globalTime) logger.debug("-> $payload") - return serializePacket(MessageId.PONG, listOf(dist, payload), sign = false) + return serializePacket(MessageId.PONG, payload, sign = false) } /* * Request deserialization */ - internal fun handleSimilarityRequest(packet: Packet) { - val (peer, remainder) = packet.getAuthPayload(cryptoProvider) - val (_, distSize) = GlobalTimeDistributionPayload.deserialize(remainder) - val (payload, _) = SimilarityRequestPayload.deserialize(remainder, distSize) + internal fun onSimilarityRequestPacket(packet: Packet) { + val (peer, payload) = + packet.getAuthPayload(SimilarityRequestPayload.Deserializer) onSimilarityRequest(peer, payload) } - internal fun handleSimilarityResponse(packet: Packet) { - val (peer, remainder) = packet.getAuthPayload(cryptoProvider) - val (_, distSize) = GlobalTimeDistributionPayload.deserialize(remainder) - val (payload, _) = SimilarityResponsePayload.deserialize(remainder, distSize) + internal fun onSimilarityResponsePacket(packet: Packet) { + val (peer, payload) = + packet.getAuthPayload(SimilarityResponsePayload.Deserializer) onSimilarityResponse(peer, payload) } - internal fun handlePing(packet: Packet) { - val remainder = packet.getPayload() - val (dist, distSize) = GlobalTimeDistributionPayload.deserialize(remainder) - val (payload, _) = PingPayload.deserialize(remainder, distSize) - onPing(packet.source, dist, payload) + internal fun onPingPacket(packet: Packet) { + val payload = packet.getPayload(PingPayload.Deserializer) + onPing(packet.source, payload) } - internal fun handlePong(packet: Packet) { - val remainder = packet.getPayload() - val (dist, distSize) = GlobalTimeDistributionPayload.deserialize(remainder) - val (payload, _) = PongPayload.deserialize(remainder, distSize) - onPong(dist, payload) + internal fun onPongPacket(packet: Packet) { + val payload = packet.getPayload(PongPayload.Deserializer) + onPong(payload) } /* @@ -127,10 +113,9 @@ class DiscoveryCommunity : Community(), PingOverlay { override fun onIntroductionResponse( peer: Peer, - dist: GlobalTimeDistributionPayload, payload: IntroductionResponsePayload ) { - super.onIntroductionResponse(peer, dist, payload) + super.onIntroductionResponse(peer, payload) sendSimilarityRequest(peer.address) } @@ -166,22 +151,18 @@ class DiscoveryCommunity : Community(), PingOverlay { internal fun onPing( address: Address, - dist: GlobalTimeDistributionPayload, payload: PingPayload ) { logger.debug("<- $payload") - logger.debug("dist = $dist") val packet = createPong(payload.identifier) send(address, packet) } internal fun onPong( - dist: GlobalTimeDistributionPayload, payload: PongPayload ) { logger.debug("<- $payload") - logger.debug("dist = $dist") val pingRequest = pingRequestCache[payload.identifier] if (pingRequest != null) { diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/Network.kt b/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/Network.kt index fb720d82..017d5dbf 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/Network.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/Network.kt @@ -87,6 +87,8 @@ class Network { for (known in verifiedPeers) { if (known.mid == peer.mid) { known.address = peer.address + known.lanAddress = peer.lanAddress + known.wanAddress = peer.wanAddress return } } diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/payload/PingPayload.kt b/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/payload/PingPayload.kt index e69ed82b..7a75d38f 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/payload/PingPayload.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/payload/PingPayload.kt @@ -9,7 +9,7 @@ data class PingPayload( return serializeUShort(identifier % 65536) } - companion object : Deserializable { + companion object Deserializer : Deserializable { override fun deserialize(buffer: ByteArray, offset: Int): Pair { val identifier = deserializeUShort(buffer, offset) return Pair(PingPayload(identifier), offset + SERIALIZED_USHORT_SIZE) diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/payload/PongPayload.kt b/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/payload/PongPayload.kt index 3145c77f..0e2baafc 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/payload/PongPayload.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/payload/PongPayload.kt @@ -9,7 +9,7 @@ data class PongPayload( return serializeUShort(identifier % 65536) } - companion object : Deserializable { + companion object Deserializer : Deserializable { override fun deserialize(buffer: ByteArray, offset: Int): Pair { val identifier = deserializeUShort(buffer, offset) return Pair(PongPayload(identifier), offset + SERIALIZED_USHORT_SIZE) diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/payload/SimilarityRequestPayload.kt b/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/payload/SimilarityRequestPayload.kt index cc54cad3..bce98985 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/payload/SimilarityRequestPayload.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/payload/SimilarityRequestPayload.kt @@ -25,7 +25,7 @@ data class SimilarityRequestPayload( preferenceList.joinToString("").hexToBytes() } - companion object : Deserializable { + companion object Deserializer : Deserializable { override fun deserialize( buffer: ByteArray, offset: Int diff --git a/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/payload/SimilarityResponsePayload.kt b/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/payload/SimilarityResponsePayload.kt index 59abf948..ec886a5b 100644 --- a/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/payload/SimilarityResponsePayload.kt +++ b/ipv8/src/main/java/nl/tudelft/ipv8/peerdiscovery/payload/SimilarityResponsePayload.kt @@ -18,7 +18,7 @@ data class SimilarityResponsePayload( preferenceList.joinToString("").hexToBytes() } - companion object : Deserializable { + companion object Deserializer : Deserializable { override fun deserialize( buffer: ByteArray, offset: Int diff --git a/ipv8/src/test/java/nl/tudelft/ipv8/CommunityTest.kt b/ipv8/src/test/java/nl/tudelft/ipv8/CommunityTest.kt index df803a3b..3d474a59 100644 --- a/ipv8/src/test/java/nl/tudelft/ipv8/CommunityTest.kt +++ b/ipv8/src/test/java/nl/tudelft/ipv8/CommunityTest.kt @@ -77,10 +77,9 @@ class CommunityTest { community.myEstimatedLan = Address("2.2.3.4", 2234) community.myEstimatedWan = Address("3.2.3.4", 3234) - val packet = community.createIntroductionRequest( + community.createIntroductionRequest( Address("1.2.3.4", 1234) ) - Assert.assertEquals("000260793bdb9cc0b60c96f88069d78aee327a6241d2f6004a4c69624e61434c504b3a7dc013cef4be5e4e051616a9b3cd9c8d8eb5192f037f3104f6323e43d83a934161ef4f7fe7ea4443da306cd998f830cf8bd543525afd929c83d641c7e9ba0ed300000000000000010102030404d20202030408ba030203040ca2010001e3e4862ec5a53c8e44e8bdeffbc8eb21cc441dbe90cc7018d4eb9183bf48d564cd86fe1d5c5d8d2298f7e2b746633ad995e2015597bfa53fb86fb70d1679a104", packet.toHex()) } @Test @@ -90,13 +89,11 @@ class CommunityTest { community.myEstimatedLan = Address("2.2.3.4", 2234) community.myEstimatedWan = Address("3.2.3.4", 3234) every { community.getPeers() } returns listOf(Peer(JavaCryptoProvider.generateKey(), Address("5.2.3.4", 5234))) - val packet = community.createIntroductionResponse( + community.createIntroductionResponse( Address("1.2.3.4", 1234), Address("1.2.3.4", 1234), 2 ) - - Assert.assertEquals("000260793bdb9cc0b60c96f88069d78aee327a6241d2f5004a4c69624e61434c504b3a7dc013cef4be5e4e051616a9b3cd9c8d8eb5192f037f3104f6323e43d83a934161ef4f7fe7ea4443da306cd998f830cf8bd543525afd929c83d641c7e9ba0ed300000000000000010102030404d20202030408ba030203040ca200000000000005020304147200000294b144e819f1b3179e8d6117ea7cf7846b4490273999f1bfd2e3c498f9486183be2464cb543003475c5cbff8458ce9e40170d332fad063e238d1dab448098801", packet.toHex()) } @Test @@ -114,9 +111,9 @@ class CommunityTest { 2 ) - community.handleIntroductionResponse(Packet(myPeer.address, packet)) + community.onIntroductionResponsePacket(Packet(myPeer.address, packet)) - verify { community.onIntroductionResponse(any(), any(), any()) } + verify { community.onIntroductionResponse(any(), any()) } } @Test @@ -144,7 +141,7 @@ class CommunityTest { val community = getCommunity() - community.deserializeIntroductionRequest(Packet(myPeer.address, receivedPayload.hexToBytes())) + community.onIntroductionRequestPacket(Packet(myPeer.address, receivedPayload.hexToBytes())) } @Test @@ -176,9 +173,9 @@ class CommunityTest { val community = spyk(getCommunity()) val packet = "000260793bdb9cc0b60c96f88069d78aee327a6241d2f9004a4c69624e61434c504b3a7dc013cef4be5e4e051616a9b3cd9c8d8eb5192f037f3104f6323e43d83a934161ef4f7fe7ea4443da306cd998f830cf8bd543525afd929c83d641c7e9ba0ed300000000000000010102030404d202030405092900016e45d66684e87a35bddf5d971619dd21de92993639b1021f85be61d940c5ba1cbd943797cfb4058c962d24d0cf19fbd4a7f6ed41e75ea2fe8693a5d876da210f" - community.handlePuncture(Packet(myPeer.address, packet.hexToBytes())) + community.onPuncturePacket(Packet(myPeer.address, packet.hexToBytes())) - verify { community.onPuncture(any(), any(), any()) } + verify { community.onPuncture(any(), any()) } } @Test @@ -201,9 +198,9 @@ class CommunityTest { val community = spyk(getCommunity()) val packet = "000260793bdb9cc0b60c96f88069d78aee327a6241d2fa00000000000000010102030404d202030405092900017b01e303fc9987b1b899445e3f9c3a0208580b3572f357e9667419cf095a8bf5ea7d97f22519695062d7db2a768ad0309afe9cb51607f0a104b623da0235c50e" - community.handlePunctureRequest(Packet(myPeer.address, packet.hexToBytes())) + community.onPunctureRequestPacket(Packet(myPeer.address, packet.hexToBytes())) - verify { community.onPunctureRequest(any(), any(), any()) } + verify { community.onPunctureRequest(any(), any()) } } @Test diff --git a/ipv8/src/test/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainBlockTest.kt b/ipv8/src/test/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainBlockTest.kt index cf056455..4da344fb 100644 --- a/ipv8/src/test/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainBlockTest.kt +++ b/ipv8/src/test/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainBlockTest.kt @@ -2,9 +2,11 @@ package nl.tudelft.ipv8.attestation.trustchain import com.goterl.lazycode.lazysodium.LazySodiumJava import com.goterl.lazycode.lazysodium.SodiumJava +import io.mockk.every import io.mockk.mockk import nl.tudelft.ipv8.attestation.trustchain.payload.HalfBlockPayload import nl.tudelft.ipv8.attestation.trustchain.store.TrustChainStore +import nl.tudelft.ipv8.attestation.trustchain.validation.ValidationErrors import nl.tudelft.ipv8.attestation.trustchain.validation.ValidationResult import nl.tudelft.ipv8.keyvault.LibNaClSK import nl.tudelft.ipv8.keyvault.PrivateKey @@ -55,7 +57,10 @@ class TrustChainBlockTest { EMPTY_SIG, Date() ) + block.sign(getPrivateKey()) val store = mockk(relaxed = true) + every { store.getBlockBefore(any()) } returns null + every { store.getBlockAfter(any()) } returns null val result = block.validate(store) Assert.assertEquals(ValidationResult.PartialNext, result) } @@ -73,9 +78,12 @@ class TrustChainBlockTest { EMPTY_SIG, Date() ) + block.sign(getPrivateKey()) val store = mockk(relaxed = true) val result = block.validate(store) Assert.assertTrue(result is ValidationResult.Invalid) + Assert.assertTrue(result is ValidationResult.Invalid && + result.errors.contains(ValidationErrors.INVALID_SEQUENCE_NUMBER)) } @Test @@ -91,9 +99,12 @@ class TrustChainBlockTest { EMPTY_SIG, Date() ) + block.sign(getPrivateKey()) val store = mockk(relaxed = true) val result = block.validate(store) Assert.assertTrue(result is ValidationResult.Invalid) + Assert.assertTrue(result is ValidationResult.Invalid && + result.errors.contains(ValidationErrors.INVALID_GENESIS_HASH)) } @Test @@ -109,8 +120,31 @@ class TrustChainBlockTest { EMPTY_SIG, Date() ) + block.sign(getPrivateKey()) val store = mockk(relaxed = true) val result = block.validate(store) Assert.assertTrue(result is ValidationResult.Invalid) + Assert.assertTrue(result is ValidationResult.Invalid && + result.errors.contains(ValidationErrors.INVALID_GENESIS_SEQUENCE_NUMBER)) + } + + @Test + fun validate_invalidSignature() { + val block = TrustChainBlock( + "custom", + "hello".toByteArray(Charsets.US_ASCII), + getPrivateKey().pub().keyToBin(), + 2u, + ANY_COUNTERPARTY_PK, + UNKNOWN_SEQ, + GENESIS_HASH, + EMPTY_SIG, + Date() + ) + val store = mockk(relaxed = true) + val result = block.validate(store) + Assert.assertTrue(result is ValidationResult.Invalid) + Assert.assertTrue(result is ValidationResult.Invalid && + result.errors.contains(ValidationErrors.INVALID_SIGNATURE)) } } diff --git a/ipv8/src/test/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainCommunityTest.kt b/ipv8/src/test/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainCommunityTest.kt index 6cbbfd5c..d85a5d83 100644 --- a/ipv8/src/test/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainCommunityTest.kt +++ b/ipv8/src/test/java/nl/tudelft/ipv8/attestation/trustchain/TrustChainCommunityTest.kt @@ -73,6 +73,8 @@ class TrustChainCommunityTest : BaseCommunityTest() { fun validateAndPersistBlock_valid() { val community = getCommunity() every { community.database.addBlock(any()) } returns Unit + every { community.database.getBlockBefore(any()) } returns null + every { community.database.getBlockAfter(any()) } returns null val customListener = mockk(relaxed = true) community.addListener("custom", customListener) @@ -92,6 +94,7 @@ class TrustChainCommunityTest : BaseCommunityTest() { EMPTY_SIG, Date() ) + block.sign(getPrivateKey()) every { community.database.contains(block) } returns false community.validateAndPersistBlock(block) @@ -110,6 +113,8 @@ class TrustChainCommunityTest : BaseCommunityTest() { every { store.getLatest(any(), any()) } returns null every { store.contains(any()) } returns false every { store.addBlock(any()) } returns Unit + every { store.getBlockBefore(any()) } returns null + every { store.getBlockAfter(any()) } returns null val block = community.createProposalBlock( "custom", @@ -134,6 +139,8 @@ class TrustChainCommunityTest : BaseCommunityTest() { every { store.getLatest(any(), any()) } returns null every { store.contains(any()) } returns false every { store.addBlock(any()) } returns Unit + every { store.getBlockBefore(any()) } returns null + every { store.getBlockAfter(any()) } returns null val block1 = TrustChainBlock( "custom", diff --git a/ipv8/src/test/java/nl/tudelft/ipv8/peerdiscovery/DiscoveryCommunityTest.kt b/ipv8/src/test/java/nl/tudelft/ipv8/peerdiscovery/DiscoveryCommunityTest.kt index 58142b92..28b10879 100644 --- a/ipv8/src/test/java/nl/tudelft/ipv8/peerdiscovery/DiscoveryCommunityTest.kt +++ b/ipv8/src/test/java/nl/tudelft/ipv8/peerdiscovery/DiscoveryCommunityTest.kt @@ -8,7 +8,6 @@ import nl.tudelft.ipv8.Peer import nl.tudelft.ipv8.keyvault.JavaCryptoProvider import nl.tudelft.ipv8.messaging.Packet import nl.tudelft.ipv8.messaging.payload.ConnectionType -import nl.tudelft.ipv8.messaging.payload.GlobalTimeDistributionPayload import nl.tudelft.ipv8.messaging.payload.IntroductionResponsePayload import org.junit.Assert.assertEquals import org.junit.Test @@ -32,7 +31,7 @@ class DiscoveryCommunityTest : BaseCommunityTest() { community.network.registerServiceProvider(community.serviceId, community) val peer = Peer(JavaCryptoProvider.generateKey(), Address("5.2.3.4", 5234)) val payload = community.createSimilarityRequest(peer) - community.handleSimilarityRequest(Packet(Address("1.2.3.4", 1234), payload)) + community.onSimilarityRequestPacket(Packet(Address("1.2.3.4", 1234), payload)) verify { community.onSimilarityRequest(any(), any()) } } @@ -50,7 +49,7 @@ class DiscoveryCommunityTest : BaseCommunityTest() { val community = spyk(getCommunity()) val peer = Peer(JavaCryptoProvider.generateKey(), Address("5.2.3.4", 5234)) val payload = community.createSimilarityResponse(123, peer) - community.handleSimilarityResponse(Packet(Address("1.2.3.4", 1234), payload)) + community.onSimilarityResponsePacket(Packet(Address("1.2.3.4", 1234), payload)) verify { community.onSimilarityResponse(any(), any()) } } @@ -58,8 +57,8 @@ class DiscoveryCommunityTest : BaseCommunityTest() { fun createPing() { val community = spyk(getCommunity()) val (_, payload) = community.createPing() - community.handlePing(Packet(Address("1.2.3.4", 1234), payload)) - verify { community.onPing(any(), any(), any()) } + community.onPingPacket(Packet(Address("1.2.3.4", 1234), payload)) + verify { community.onPing(any(), any()) } } @Test @@ -73,8 +72,8 @@ class DiscoveryCommunityTest : BaseCommunityTest() { fun createPong() { val community = spyk(getCommunity()) val payload = community.createPong(123) - community.handlePong(Packet(Address("1.2.3.4", 1234), payload)) - verify { community.onPong(any(), any()) } + community.onPongPacket(Packet(Address("1.2.3.4", 1234), payload)) + verify { community.onPong(any()) } } @Test @@ -84,7 +83,7 @@ class DiscoveryCommunityTest : BaseCommunityTest() { community.sendPing(peer) val payload = community.createPong(1) - community.handlePong(Packet(Address("1.2.3.4", 1234), payload)) + community.onPongPacket(Packet(Address("1.2.3.4", 1234), payload)) assertEquals(1, peer.pings.size) } @@ -93,7 +92,6 @@ class DiscoveryCommunityTest : BaseCommunityTest() { fun onIntroductionResponse_sendSimilarityRequest() { val community = spyk(getCommunity()) val peer = Peer(JavaCryptoProvider.generateKey(), Address("5.2.3.4", 5234)) - val dist = GlobalTimeDistributionPayload(1u) val payload = IntroductionResponsePayload( Address("1.2.3.4", 1234), Address("2.2.3.4", 2234), @@ -104,7 +102,7 @@ class DiscoveryCommunityTest : BaseCommunityTest() { false, 2 ) - community.onIntroductionResponse(peer, dist, payload) + community.onIntroductionResponse(peer, payload) verify { community.sendSimilarityRequest(peer.address) } } @@ -133,7 +131,7 @@ class DiscoveryCommunityTest : BaseCommunityTest() { community1.maxPeers = 1 network1.registerServiceProvider(community1.serviceId, community1) val payload1 = community1.createSimilarityResponse(123, peer1) - community.handleSimilarityResponse(Packet(Address("13.2.3.4", 1234), payload1)) + community.onSimilarityResponsePacket(Packet(Address("13.2.3.4", 1234), payload1)) assertEquals(1, community.getPeers().size) assertEquals(2, network.verifiedPeers.size) @@ -146,7 +144,7 @@ class DiscoveryCommunityTest : BaseCommunityTest() { community2.maxPeers = 1 network2.registerServiceProvider(community2.serviceId, community2) val payload2 = community2.createSimilarityResponse(123, peer2) - community.handleSimilarityResponse(Packet(Address("14.2.3.4", 5234), payload2)) + community.onSimilarityResponsePacket(Packet(Address("14.2.3.4", 5234), payload2)) assertEquals(1, community.getPeers().size) assertEquals(2, network.verifiedPeers.size)