mirror of
https://github.com/corda/corda.git
synced 2025-06-19 07:38:22 +00:00
Error if multiple nodes match a key
InMemoryNetworkMapCache.getNodeByPublicKey() previously returned null if multiple nodes matched a given public key (for example if the same node is registered more than once with different names). This is incorrect behaviour, as there is a match.
This commit is contained in:
@ -6,6 +6,7 @@ import com.google.common.util.concurrent.SettableFuture
|
|||||||
import com.r3corda.core.bufferUntilSubscribed
|
import com.r3corda.core.bufferUntilSubscribed
|
||||||
import com.r3corda.core.contracts.Contract
|
import com.r3corda.core.contracts.Contract
|
||||||
import com.r3corda.core.crypto.Party
|
import com.r3corda.core.crypto.Party
|
||||||
|
import com.r3corda.core.crypto.toStringShort
|
||||||
import com.r3corda.core.map
|
import com.r3corda.core.map
|
||||||
import com.r3corda.core.messaging.MessagingService
|
import com.r3corda.core.messaging.MessagingService
|
||||||
import com.r3corda.core.messaging.SingleMessageRecipient
|
import com.r3corda.core.messaging.SingleMessageRecipient
|
||||||
@ -72,9 +73,16 @@ open class InMemoryNetworkMapCache : SingletonSerializeAsToken(), NetworkMapCach
|
|||||||
override fun get(serviceType: ServiceType) = registeredNodes.filterValues { it.advertisedServices.any { it.info.type.isSubTypeOf(serviceType) } }.map { it.value }
|
override fun get(serviceType: ServiceType) = registeredNodes.filterValues { it.advertisedServices.any { it.info.type.isSubTypeOf(serviceType) } }.map { it.value }
|
||||||
override fun getRecommended(type: ServiceType, contract: Contract, vararg party: Party): NodeInfo? = get(type).firstOrNull()
|
override fun getRecommended(type: ServiceType, contract: Contract, vararg party: Party): NodeInfo? = get(type).firstOrNull()
|
||||||
override fun getNodeByLegalName(name: String) = get().singleOrNull { it.legalIdentity.name == name }
|
override fun getNodeByLegalName(name: String) = get().singleOrNull { it.legalIdentity.name == name }
|
||||||
override fun getNodeByPublicKey(publicKey: PublicKey) = get().singleOrNull {
|
override fun getNodeByPublicKey(publicKey: PublicKey): NodeInfo? {
|
||||||
(it.legalIdentity.owningKey == publicKey)
|
// Although we should never have more than one match, it is theoretically possible. Report an error if it happens.
|
||||||
|| it.advertisedServices.any { it.identity.owningKey == publicKey }
|
val candidates = get().filter {
|
||||||
|
(it.legalIdentity.owningKey == publicKey)
|
||||||
|
|| it.advertisedServices.any { it.identity.owningKey == publicKey }
|
||||||
|
}
|
||||||
|
if (candidates.size > 1) {
|
||||||
|
throw IllegalStateException("Found more than one match for key ${publicKey.toStringShort()}")
|
||||||
|
}
|
||||||
|
return candidates.singleOrNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addMapService(net: MessagingService, networkMapAddress: SingleMessageRecipient, subscribe: Boolean,
|
override fun addMapService(net: MessagingService, networkMapAddress: SingleMessageRecipient, subscribe: Boolean,
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
package com.r3corda.node.services
|
package com.r3corda.node.services
|
||||||
|
|
||||||
|
import com.r3corda.core.crypto.generateKeyPair
|
||||||
|
import com.r3corda.core.node.services.ServiceInfo
|
||||||
|
import com.r3corda.node.services.network.NetworkMapService
|
||||||
|
import com.r3corda.node.services.transactions.SimpleNotaryService
|
||||||
|
import com.r3corda.testing.expect
|
||||||
import com.r3corda.testing.node.MockNetwork
|
import com.r3corda.testing.node.MockNetwork
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class InMemoryNetworkMapCacheTest {
|
class InMemoryNetworkMapCacheTest {
|
||||||
lateinit var network: MockNetwork
|
lateinit var network: MockNetwork
|
||||||
@ -20,4 +26,20 @@ class InMemoryNetworkMapCacheTest {
|
|||||||
network.runNetwork()
|
network.runNetwork()
|
||||||
future.get()
|
future.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `key collision`() {
|
||||||
|
val keyPair = generateKeyPair()
|
||||||
|
val nodeA = network.createNode(null, -1, MockNetwork.DefaultFactory, true, "Node A", keyPair, ServiceInfo(NetworkMapService.type))
|
||||||
|
val nodeB = network.createNode(null, -1, MockNetwork.DefaultFactory, true, "Node B", keyPair, ServiceInfo(NetworkMapService.type))
|
||||||
|
|
||||||
|
// Node A currently knows only about itself, so this returns node A
|
||||||
|
assertEquals(nodeA.netMapCache.getNodeByPublicKey(keyPair.public), nodeA.info)
|
||||||
|
|
||||||
|
nodeA.netMapCache.addNode(nodeB.info)
|
||||||
|
// Now both nodes match, so it throws an error
|
||||||
|
expect<IllegalStateException> {
|
||||||
|
nodeA.netMapCache.getNodeByPublicKey(keyPair.public)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user