mirror of
https://github.com/corda/corda.git
synced 2025-06-16 22:28:15 +00:00
Remove notaryIdentityKey from ServiceHub (#1541)
* Remove notaryIdentityKey from ServiceHub It was redundant, as we have notary field on a transaction. Notaries can use this field to check if the transaction was meant for them and then use that information while choosing a key to sign a transaction. * Move notaryIdentityKey to NotaryService * Address comments * Fixes after rebase
This commit is contained in:
committed by
josecoll
parent
adb8c5ead2
commit
002c6c4687
@ -255,9 +255,16 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
*/
|
||||
fun <T : SerializeAsToken> installCordaService(serviceClass: Class<T>): T {
|
||||
serviceClass.requireAnnotation<CordaService>()
|
||||
val constructor = serviceClass.getDeclaredConstructor(ServiceHub::class.java).apply { isAccessible = true }
|
||||
val service = try {
|
||||
constructor.newInstance(services)
|
||||
if (NotaryService::class.java.isAssignableFrom(serviceClass)) {
|
||||
check(myNotaryIdentity != null) { "Trying to install a notary service but no notary identity specified" }
|
||||
val constructor = serviceClass.getDeclaredConstructor(ServiceHub::class.java, PublicKey::class.java).apply { isAccessible = true }
|
||||
constructor.newInstance(services, myNotaryIdentity!!.owningKey)
|
||||
}
|
||||
else {
|
||||
val constructor = serviceClass.getDeclaredConstructor(ServiceHub::class.java).apply { isAccessible = true }
|
||||
constructor.newInstance(services)
|
||||
}
|
||||
} catch (e: InvocationTargetException) {
|
||||
throw ServiceInstantiationException(e.cause)
|
||||
}
|
||||
@ -576,12 +583,13 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
}
|
||||
|
||||
open protected fun makeCoreNotaryService(type: ServiceType): NotaryService? {
|
||||
check(myNotaryIdentity != null) { "No notary identity initialized when creating a notary service" }
|
||||
return when (type) {
|
||||
SimpleNotaryService.type -> SimpleNotaryService(services)
|
||||
ValidatingNotaryService.type -> ValidatingNotaryService(services)
|
||||
RaftNonValidatingNotaryService.type -> RaftNonValidatingNotaryService(services)
|
||||
RaftValidatingNotaryService.type -> RaftValidatingNotaryService(services)
|
||||
BFTNonValidatingNotaryService.type -> BFTNonValidatingNotaryService(services)
|
||||
SimpleNotaryService.type -> SimpleNotaryService(services, myNotaryIdentity!!.owningKey)
|
||||
ValidatingNotaryService.type -> ValidatingNotaryService(services, myNotaryIdentity!!.owningKey)
|
||||
RaftNonValidatingNotaryService.type -> RaftNonValidatingNotaryService(services, myNotaryIdentity!!.owningKey)
|
||||
RaftValidatingNotaryService.type -> RaftValidatingNotaryService(services, myNotaryIdentity!!.owningKey)
|
||||
BFTNonValidatingNotaryService.type -> BFTNonValidatingNotaryService(services, myNotaryIdentity!!.owningKey)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
@ -713,7 +721,6 @@ abstract class AbstractNode(open val configuration: NodeConfiguration,
|
||||
override val myInfo: NodeInfo get() = info
|
||||
override val database: CordaPersistence get() = this@AbstractNode.database
|
||||
override val configuration: NodeConfiguration get() = this@AbstractNode.configuration
|
||||
override val notaryIdentityKey: PublicKey get() = myNotaryIdentity?.owningKey ?: throw IllegalArgumentException("Node doesn't have notary identity key")
|
||||
|
||||
override fun <T : SerializeAsToken> cordaService(type: Class<T>): T {
|
||||
require(type.isAnnotationPresent(CordaService::class.java)) { "${type.name} is not a Corda service" }
|
||||
|
@ -6,6 +6,7 @@ import net.corda.core.contracts.StateRef
|
||||
import net.corda.core.crypto.DigitalSignature
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.NotaryError
|
||||
import net.corda.core.flows.NotaryException
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
@ -20,6 +21,7 @@ import net.corda.core.utilities.*
|
||||
import net.corda.node.services.api.ServiceHubInternal
|
||||
import net.corda.node.utilities.AppendOnlyPersistentMap
|
||||
import net.corda.node.utilities.NODE_DATABASE_PREFIX
|
||||
import java.security.PublicKey
|
||||
import javax.persistence.Entity
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
@ -28,7 +30,9 @@ import kotlin.concurrent.thread
|
||||
*
|
||||
* A transaction is notarised when the consensus is reached by the cluster on its uniqueness, and time-window validity.
|
||||
*/
|
||||
class BFTNonValidatingNotaryService(override val services: ServiceHubInternal, cluster: BFTSMaRt.Cluster = distributedCluster) : NotaryService() {
|
||||
class BFTNonValidatingNotaryService(override val services: ServiceHubInternal,
|
||||
override val notaryIdentityKey: PublicKey,
|
||||
cluster: BFTSMaRt.Cluster = distributedCluster) : NotaryService() {
|
||||
companion object {
|
||||
val type = SimpleNotaryService.type.getSubType("bft")
|
||||
private val log = loggerFor<BFTNonValidatingNotaryService>()
|
||||
@ -51,7 +55,7 @@ class BFTNonValidatingNotaryService(override val services: ServiceHubInternal, c
|
||||
thread(name = "BFT SMaRt replica $replicaId init", isDaemon = true) {
|
||||
configHandle.use {
|
||||
val timeWindowChecker = TimeWindowChecker(services.clock)
|
||||
val replica = Replica(it, replicaId, { createMap() }, services, timeWindowChecker)
|
||||
val replica = Replica(it, replicaId, { createMap() }, services, notaryIdentityKey, timeWindowChecker)
|
||||
replicaHolder.set(replica)
|
||||
log.info("BFT SMaRt replica $replicaId is running.")
|
||||
}
|
||||
@ -100,8 +104,8 @@ class BFTNonValidatingNotaryService(override val services: ServiceHubInternal, c
|
||||
toPersistentEntityKey = { PersistentStateRef(it.txhash.toString(), it.index) },
|
||||
fromPersistentEntity = {
|
||||
//TODO null check will become obsolete after making DB/JPA columns not nullable
|
||||
var txId = it.id.txId ?: throw IllegalStateException("DB returned null SecureHash transactionId")
|
||||
var index = it.id.index ?: throw IllegalStateException("DB returned null SecureHash index")
|
||||
val txId = it.id.txId ?: throw IllegalStateException("DB returned null SecureHash transactionId")
|
||||
val index = it.id.index ?: throw IllegalStateException("DB returned null SecureHash index")
|
||||
Pair(StateRef(txhash = SecureHash.parse(txId), index = index),
|
||||
UniquenessProvider.ConsumingTx(
|
||||
id = SecureHash.parse(it.consumingTxHash),
|
||||
@ -126,7 +130,8 @@ class BFTNonValidatingNotaryService(override val services: ServiceHubInternal, c
|
||||
replicaId: Int,
|
||||
createMap: () -> AppendOnlyPersistentMap<StateRef, UniquenessProvider.ConsumingTx, PersistedCommittedState, PersistentStateRef>,
|
||||
services: ServiceHubInternal,
|
||||
timeWindowChecker: TimeWindowChecker) : BFTSMaRt.Replica(config, replicaId, createMap, services, timeWindowChecker) {
|
||||
notaryIdentityKey: PublicKey,
|
||||
timeWindowChecker: TimeWindowChecker) : BFTSMaRt.Replica(config, replicaId, createMap, services, notaryIdentityKey, timeWindowChecker) {
|
||||
|
||||
override fun executeCommand(command: ByteArray): ByteArray {
|
||||
val request = command.deserialize<BFTSMaRt.CommitRequest>()
|
||||
@ -139,8 +144,9 @@ class BFTNonValidatingNotaryService(override val services: ServiceHubInternal, c
|
||||
return try {
|
||||
val id = ftx.id
|
||||
val inputs = ftx.inputs
|
||||
|
||||
val notary = ftx.notary
|
||||
validateTimeWindow(ftx.timeWindow)
|
||||
if (notary !in services.myInfo.legalIdentities) throw NotaryException(NotaryError.WrongNotary)
|
||||
commitInputStates(inputs, id, callerIdentity)
|
||||
log.debug { "Inputs committed successfully, signing $id" }
|
||||
BFTSMaRt.ReplicaResponse.Signature(sign(ftx))
|
||||
|
@ -36,6 +36,7 @@ import net.corda.node.services.transactions.BFTSMaRt.Client
|
||||
import net.corda.node.services.transactions.BFTSMaRt.Replica
|
||||
import net.corda.node.utilities.AppendOnlyPersistentMap
|
||||
import java.nio.file.Path
|
||||
import java.security.PublicKey
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
@ -176,6 +177,7 @@ object BFTSMaRt {
|
||||
createMap: () -> AppendOnlyPersistentMap<StateRef, UniquenessProvider.ConsumingTx,
|
||||
BFTNonValidatingNotaryService.PersistedCommittedState, PersistentStateRef>,
|
||||
protected val services: ServiceHubInternal,
|
||||
protected val notaryIdentityKey: PublicKey,
|
||||
private val timeWindowChecker: TimeWindowChecker) : DefaultRecoverable() {
|
||||
companion object {
|
||||
private val log = loggerFor<Replica>()
|
||||
@ -248,11 +250,11 @@ object BFTSMaRt {
|
||||
}
|
||||
|
||||
protected fun sign(bytes: ByteArray): DigitalSignature.WithKey {
|
||||
return services.database.transaction { services.keyManagementService.sign(bytes, services.notaryIdentityKey) }
|
||||
return services.database.transaction { services.keyManagementService.sign(bytes, notaryIdentityKey) }
|
||||
}
|
||||
|
||||
protected fun sign(filteredTransaction: FilteredTransaction): TransactionSignature {
|
||||
return services.database.transaction { services.createSignature(filteredTransaction, services.notaryIdentityKey) }
|
||||
return services.database.transaction { services.createSignature(filteredTransaction, notaryIdentityKey) }
|
||||
}
|
||||
|
||||
// TODO:
|
||||
|
@ -27,9 +27,10 @@ class NonValidatingNotaryFlow(otherSide: Party, service: TrustedAuthorityNotaryS
|
||||
it.verify()
|
||||
it.checkAllComponentsVisible(ComponentGroupEnum.INPUTS_GROUP)
|
||||
it.checkAllComponentsVisible(ComponentGroupEnum.TIMEWINDOW_GROUP)
|
||||
TransactionParts(it.id, it.inputs, it.timeWindow)
|
||||
val notary = it.notary
|
||||
TransactionParts(it.id, it.inputs, it.timeWindow, notary)
|
||||
}
|
||||
is NotaryChangeWireTransaction -> TransactionParts(it.id, it.inputs, null)
|
||||
is NotaryChangeWireTransaction -> TransactionParts(it.id, it.inputs, null, it.notary)
|
||||
else -> {
|
||||
throw IllegalArgumentException("Received unexpected transaction type: ${it::class.java.simpleName}," +
|
||||
"expected either ${FilteredTransaction::class.java.simpleName} or ${NotaryChangeWireTransaction::class.java.simpleName}")
|
||||
|
@ -5,9 +5,10 @@ import net.corda.core.identity.Party
|
||||
import net.corda.core.node.services.TimeWindowChecker
|
||||
import net.corda.core.node.services.TrustedAuthorityNotaryService
|
||||
import net.corda.node.services.api.ServiceHubInternal
|
||||
import java.security.PublicKey
|
||||
|
||||
/** A non-validating notary service operated by a group of mutually trusting parties, uses the Raft algorithm to achieve consensus. */
|
||||
class RaftNonValidatingNotaryService(override val services: ServiceHubInternal) : TrustedAuthorityNotaryService() {
|
||||
class RaftNonValidatingNotaryService(override val services: ServiceHubInternal, override val notaryIdentityKey: PublicKey) : TrustedAuthorityNotaryService() {
|
||||
companion object {
|
||||
val type = SimpleNotaryService.type.getSubType("raft")
|
||||
}
|
||||
|
@ -5,9 +5,10 @@ import net.corda.core.identity.Party
|
||||
import net.corda.core.node.services.TimeWindowChecker
|
||||
import net.corda.core.node.services.TrustedAuthorityNotaryService
|
||||
import net.corda.node.services.api.ServiceHubInternal
|
||||
import java.security.PublicKey
|
||||
|
||||
/** A validating notary service operated by a group of mutually trusting parties, uses the Raft algorithm to achieve consensus. */
|
||||
class RaftValidatingNotaryService(override val services: ServiceHubInternal) : TrustedAuthorityNotaryService() {
|
||||
class RaftValidatingNotaryService(override val services: ServiceHubInternal, override val notaryIdentityKey: PublicKey) : TrustedAuthorityNotaryService() {
|
||||
companion object {
|
||||
val type = ValidatingNotaryService.type.getSubType("raft")
|
||||
}
|
||||
|
@ -6,9 +6,10 @@ import net.corda.core.node.services.TimeWindowChecker
|
||||
import net.corda.core.node.services.TrustedAuthorityNotaryService
|
||||
import net.corda.nodeapi.ServiceType
|
||||
import net.corda.node.services.api.ServiceHubInternal
|
||||
import java.security.PublicKey
|
||||
|
||||
/** A simple Notary service that does not perform transaction validation */
|
||||
class SimpleNotaryService(override val services: ServiceHubInternal) : TrustedAuthorityNotaryService() {
|
||||
class SimpleNotaryService(override val services: ServiceHubInternal, override val notaryIdentityKey: PublicKey) : TrustedAuthorityNotaryService() {
|
||||
companion object {
|
||||
val type = ServiceType.notary.getSubType("simple")
|
||||
}
|
||||
|
@ -24,9 +24,11 @@ class ValidatingNotaryFlow(otherSide: Party, service: TrustedAuthorityNotaryServ
|
||||
override fun receiveAndVerifyTx(): TransactionParts {
|
||||
try {
|
||||
val stx = subFlow(ReceiveTransactionFlow(otherSide, checkSufficientSignatures = false))
|
||||
val notary = stx.notary
|
||||
checkNotary(notary)
|
||||
checkSignatures(stx)
|
||||
val wtx = stx.tx
|
||||
return TransactionParts(wtx.id, wtx.inputs, wtx.timeWindow)
|
||||
return TransactionParts(wtx.id, wtx.inputs, wtx.timeWindow, notary!!)
|
||||
} catch (e: Exception) {
|
||||
throw when (e) {
|
||||
is TransactionVerificationException,
|
||||
@ -38,7 +40,7 @@ class ValidatingNotaryFlow(otherSide: Party, service: TrustedAuthorityNotaryServ
|
||||
|
||||
private fun checkSignatures(stx: SignedTransaction) {
|
||||
try {
|
||||
stx.verifySignaturesExcept(serviceHub.notaryIdentityKey)
|
||||
stx.verifySignaturesExcept(service.notaryIdentityKey)
|
||||
} catch(e: SignatureException) {
|
||||
throw NotaryException(NotaryError.TransactionInvalid(e))
|
||||
}
|
||||
|
@ -6,9 +6,10 @@ import net.corda.core.node.services.TimeWindowChecker
|
||||
import net.corda.core.node.services.TrustedAuthorityNotaryService
|
||||
import net.corda.nodeapi.ServiceType
|
||||
import net.corda.node.services.api.ServiceHubInternal
|
||||
import java.security.PublicKey
|
||||
|
||||
/** A Notary service that validates the transaction chain of the submitted transaction before committing it */
|
||||
class ValidatingNotaryService(override val services: ServiceHubInternal) : TrustedAuthorityNotaryService() {
|
||||
class ValidatingNotaryService(override val services: ServiceHubInternal, override val notaryIdentityKey: PublicKey) : TrustedAuthorityNotaryService() {
|
||||
companion object {
|
||||
val type = ServiceType.notary.getSubType("validating")
|
||||
}
|
||||
|
@ -646,7 +646,8 @@ class TwoPartyTradeFlowTests {
|
||||
val sigs = mutableListOf<TransactionSignature>()
|
||||
val nodeKey = node.info.chooseIdentity().owningKey
|
||||
sigs.add(node.services.keyManagementService.sign(SignableData(id, SignatureMetadata(1, Crypto.findSignatureScheme(nodeKey).schemeNumberID)), nodeKey))
|
||||
sigs.add(notaryNode.services.keyManagementService.sign(SignableData(id, SignatureMetadata(1, Crypto.findSignatureScheme(notaryNode.services.notaryIdentityKey).schemeNumberID)), notaryNode.services.notaryIdentityKey))
|
||||
sigs.add(notaryNode.services.keyManagementService.sign(SignableData(id, SignatureMetadata(1,
|
||||
Crypto.findSignatureScheme(notaryNode.info.legalIdentities[1].owningKey).schemeNumberID)), notaryNode.info.legalIdentities[1].owningKey))
|
||||
extraSigningNodes.forEach { currentNode ->
|
||||
sigs.add(currentNode.services.keyManagementService.sign(
|
||||
SignableData(id, SignatureMetadata(1, Crypto.findSignatureScheme(currentNode.info.chooseIdentity().owningKey).schemeNumberID)),
|
||||
|
@ -161,7 +161,7 @@ class NotaryServiceTests {
|
||||
fun issueState(node: StartedNode<*>): StateAndRef<*> {
|
||||
val tx = DummyContract.generateInitial(Random().nextInt(), notary, node.info.chooseIdentity().ref(0))
|
||||
val signedByNode = node.services.signInitialTransaction(tx)
|
||||
val stx = notaryNode.services.addSignature(signedByNode, notaryNode.services.notaryIdentityKey)
|
||||
val stx = notaryNode.services.addSignature(signedByNode, notary.owningKey)
|
||||
node.services.recordTransactions(stx)
|
||||
return StateAndRef(tx.outputStates().first(), StateRef(stx.id, 0))
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ class ValidatingNotaryServiceTests {
|
||||
fun issueState(node: StartedNode<*>): StateAndRef<*> {
|
||||
val tx = DummyContract.generateInitial(Random().nextInt(), notary, node.info.chooseIdentity().ref(0))
|
||||
val signedByNode = node.services.signInitialTransaction(tx)
|
||||
val stx = notaryNode.services.addSignature(signedByNode, notaryNode.services.notaryIdentityKey)
|
||||
val stx = notaryNode.services.addSignature(signedByNode, notary.owningKey)
|
||||
node.services.recordTransactions(stx)
|
||||
return StateAndRef(tx.outputStates().first(), StateRef(stx.id, 0))
|
||||
}
|
||||
|
Reference in New Issue
Block a user