mirror of
https://github.com/corda/corda.git
synced 2025-04-07 11:27:01 +00:00
CORDA-2745: Cache notary identity lookups (#4892)
Add a cache for notary identities in the PersistentIdentityService. This solves a reported problem where notary identity lookup fails if its network map entry is missing, which results in an exception when trying to insert a state into the vault after recording a transaction.
This commit is contained in:
parent
82c45c6f83
commit
e3ada049d4
@ -343,7 +343,7 @@ abstract class AbstractNode<S>(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)
|
||||
|
@ -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<Party>()
|
||||
|
||||
// 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<X509Certificate> = emptyList()) {
|
||||
fun start(trustRoot: X509Certificate, caCertificates: List<X509Certificate> = emptyList(), notaryIdentities: List<Party> = emptyList()) {
|
||||
_trustRoot = trustRoot
|
||||
_trustAnchor = TrustAnchor(trustRoot, null)
|
||||
_caCertStore = CertStore.getInstance("Collection", CollectionCertStoreParameters(caCertificates.toSet() + trustRoot))
|
||||
notaryIdentityCache.addAll(notaryIdentities)
|
||||
}
|
||||
|
||||
fun loadIdentities(identities: Collection<PartyAndCertificate> = emptySet(), confidentialIdentities: Collection<PartyAndCertificate> = 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<Party> {
|
||||
return database.transaction {
|
||||
@ -194,5 +207,4 @@ class PersistentIdentityService(cacheFactory: NamedCacheFactory) : SingletonSeri
|
||||
fun stripNotOurKeys(keys: Iterable<PublicKey>): Iterable<PublicKey> {
|
||||
return keys.filter { certificateFromKey(it)?.name in ourNames }
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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? {
|
||||
|
Loading…
x
Reference in New Issue
Block a user