diff --git a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt index 8a1bc980c8..0063bb6d31 100644 --- a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt +++ b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt @@ -343,7 +343,7 @@ abstract class AbstractNode(val configuration: NodeConfiguration, X509Utilities.validateCertPath(trustRoot, identity.certPath) val nodeCa = configuration.signingCertificateStore.get()[CORDA_CLIENT_CA] - identityService.start(trustRoot, listOf(identity.certificate, nodeCa)) + identityService.start(trustRoot, listOf(identity.certificate, nodeCa), netParams.notaries.map { it.identity }) val (keyPairs, nodeInfoAndSigned, myNotaryIdentity) = database.transaction { updateNodeInfo(identity, identityKeyPair, publish = true) diff --git a/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt b/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt index 552ccd36dc..2fe6d1deb8 100644 --- a/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt +++ b/node/src/main/kotlin/net/corda/node/services/identity/PersistentIdentityService.kt @@ -101,16 +101,20 @@ class PersistentIdentityService(cacheFactory: NamedCacheFactory) : SingletonSeri private lateinit var _trustAnchor: TrustAnchor override val trustAnchor: TrustAnchor get() = _trustAnchor + /** Stores notary identities obtained from the network parameters, for which we don't need to perform a database lookup. */ + private val notaryIdentityCache = HashSet() + // CordaPersistence is not a c'tor parameter to work around the cyclic dependency lateinit var database: CordaPersistence private val keyToParties = createPKMap(cacheFactory) private val principalToParties = createX500Map(cacheFactory) - fun start(trustRoot: X509Certificate, caCertificates: List = emptyList()) { + fun start(trustRoot: X509Certificate, caCertificates: List = emptyList(), notaryIdentities: List = emptyList()) { _trustRoot = trustRoot _trustAnchor = TrustAnchor(trustRoot, null) _caCertStore = CertStore.getInstance("Collection", CollectionCertStoreParameters(caCertificates.toSet() + trustRoot)) + notaryIdentityCache.addAll(notaryIdentities) } fun loadIdentities(identities: Collection = emptySet(), confidentialIdentities: Collection = emptySet()) { @@ -170,7 +174,16 @@ class PersistentIdentityService(cacheFactory: NamedCacheFactory) : SingletonSeri override fun wellKnownPartyFromX500Name(name: CordaX500Name): Party? = certificateFromCordaX500Name(name)?.party - override fun wellKnownPartyFromAnonymous(party: AbstractParty): Party? = database.transaction { super.wellKnownPartyFromAnonymous(party) } + override fun wellKnownPartyFromAnonymous(party: AbstractParty): Party? { + // Skip database lookup if the party is a notary identity. + // This also prevents an issue where the notary identity can't be resolved if it's not in the network map cache. The node obtains + // a trusted list of notary identities from the network parameters automatically. + return if (party is Party && party in notaryIdentityCache) { + party + } else { + database.transaction { super.wellKnownPartyFromAnonymous(party) } + } + } override fun partiesFromName(query: String, exactMatch: Boolean): Set { return database.transaction { @@ -194,5 +207,4 @@ class PersistentIdentityService(cacheFactory: NamedCacheFactory) : SingletonSeri fun stripNotOurKeys(keys: Iterable): Iterable { return keys.filter { certificateFromKey(it)?.name in ourNames } } - } diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/AbstractPartyToX500NameAsStringConverter.kt b/node/src/main/kotlin/net/corda/node/services/persistence/AbstractPartyToX500NameAsStringConverter.kt index b476872172..078447854a 100644 --- a/node/src/main/kotlin/net/corda/node/services/persistence/AbstractPartyToX500NameAsStringConverter.kt +++ b/node/src/main/kotlin/net/corda/node/services/persistence/AbstractPartyToX500NameAsStringConverter.kt @@ -8,8 +8,8 @@ import javax.persistence.AttributeConverter import javax.persistence.Converter /** - * Converter to persist a party as its' well known identity (where resolvable). - * Completely anonymous parties are stored as null (to preserve privacy). + * Converter to persist a party as its well known identity (where resolvable). + * Completely anonymous parties are stored as *null* (to preserve privacy). */ @Converter(autoApply = true) class AbstractPartyToX500NameAsStringConverter(private val wellKnownPartyFromX500Name: (CordaX500Name) -> Party?, @@ -24,7 +24,7 @@ class AbstractPartyToX500NameAsStringConverter(private val wellKnownPartyFromX50 if (partyName != null) return partyName log.warn("Identity service unable to resolve AbstractParty: $party") } - return null // non resolvable anonymous parties + return null // non resolvable anonymous parties are stored as nulls } override fun convertToEntityAttribute(dbData: String?): AbstractParty? {