mirror of
https://github.com/corda/corda.git
synced 2024-12-23 14:52:29 +00:00
State replacement protocols: preserve the UntrustworthyData<T> marker for longer to try and get subclass authors in the right frame of mind.
This commit is contained in:
parent
b89f86d013
commit
793e912324
@ -1,7 +1,9 @@
|
|||||||
package com.r3corda.protocols
|
package com.r3corda.protocols
|
||||||
|
|
||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import com.r3corda.core.contracts.*
|
import com.r3corda.core.contracts.ContractState
|
||||||
|
import com.r3corda.core.contracts.StateAndRef
|
||||||
|
import com.r3corda.core.contracts.StateRef
|
||||||
import com.r3corda.core.crypto.DigitalSignature
|
import com.r3corda.core.crypto.DigitalSignature
|
||||||
import com.r3corda.core.crypto.Party
|
import com.r3corda.core.crypto.Party
|
||||||
import com.r3corda.core.crypto.signWithECDSA
|
import com.r3corda.core.crypto.signWithECDSA
|
||||||
@ -12,6 +14,7 @@ import com.r3corda.core.random63BitValue
|
|||||||
import com.r3corda.core.transactions.SignedTransaction
|
import com.r3corda.core.transactions.SignedTransaction
|
||||||
import com.r3corda.core.transactions.WireTransaction
|
import com.r3corda.core.transactions.WireTransaction
|
||||||
import com.r3corda.core.utilities.ProgressTracker
|
import com.r3corda.core.utilities.ProgressTracker
|
||||||
|
import com.r3corda.core.utilities.UntrustworthyData
|
||||||
import com.r3corda.protocols.AbstractStateReplacementProtocol.Acceptor
|
import com.r3corda.protocols.AbstractStateReplacementProtocol.Acceptor
|
||||||
import com.r3corda.protocols.AbstractStateReplacementProtocol.Instigator
|
import com.r3corda.protocols.AbstractStateReplacementProtocol.Instigator
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
@ -119,7 +122,7 @@ abstract class AbstractStateReplacementProtocol<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class Acceptor<in T>(val otherSide: Party,
|
abstract class Acceptor<T>(val otherSide: Party,
|
||||||
val sessionIdForSend: Long,
|
val sessionIdForSend: Long,
|
||||||
val sessionIdForReceive: Long,
|
val sessionIdForReceive: Long,
|
||||||
override val progressTracker: ProgressTracker = tracker()) : ProtocolLogic<Unit>() {
|
override val progressTracker: ProgressTracker = tracker()) : ProtocolLogic<Unit>() {
|
||||||
@ -137,24 +140,21 @@ abstract class AbstractStateReplacementProtocol<T> {
|
|||||||
@Suspendable
|
@Suspendable
|
||||||
override fun call() {
|
override fun call() {
|
||||||
progressTracker.currentStep = VERIFYING
|
progressTracker.currentStep = VERIFYING
|
||||||
val proposal = receive<Proposal<T>>(sessionIdForReceive).validate { it }
|
val maybeProposal: UntrustworthyData<Proposal<T>> = receive(sessionIdForReceive)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
verifyProposal(proposal)
|
val stx: SignedTransaction = maybeProposal.validate { verifyProposal(maybeProposal).stx }
|
||||||
verifyTx(proposal.stx)
|
verifyTx(stx)
|
||||||
|
approve(stx)
|
||||||
} catch(e: Exception) {
|
} catch(e: Exception) {
|
||||||
// TODO: catch only specific exceptions. However, there are numerous validation exceptions
|
// TODO: catch only specific exceptions. However, there are numerous validation exceptions
|
||||||
// that might occur (tx validation/resolution, invalid proposal). Need to rethink how
|
// that might occur (tx validation/resolution, invalid proposal). Need to rethink how
|
||||||
// we manage exceptions and maybe introduce some platform exception hierarchy
|
// we manage exceptions and maybe introduce some platform exception hierarchy
|
||||||
val myIdentity = serviceHub.storageService.myLegalIdentity
|
val myIdentity = serviceHub.storageService.myLegalIdentity
|
||||||
val state = proposal.stateRef
|
val state = maybeProposal.validate { it.stateRef }
|
||||||
val reason = StateReplacementRefused(myIdentity, state, e.message)
|
val reason = StateReplacementRefused(myIdentity, state, e.message)
|
||||||
|
|
||||||
reject(reason)
|
reject(reason)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
approve(proposal.stx)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suspendable
|
@Suspendable
|
||||||
@ -185,9 +185,10 @@ abstract class AbstractStateReplacementProtocol<T> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the state change proposal to confirm that it's acceptable to this node. Rules for verification depend
|
* Check the state change proposal to confirm that it's acceptable to this node. Rules for verification depend
|
||||||
* on the change proposed, and may further depend on the node itself (for example configuration).
|
* on the change proposed, and may further depend on the node itself (for example configuration). The
|
||||||
|
* proposal is returned if acceptable, otherwise an exception is thrown.
|
||||||
*/
|
*/
|
||||||
abstract internal fun verifyProposal(proposal: Proposal<T>)
|
abstract fun verifyProposal(maybeProposal: UntrustworthyData<Proposal<T>>): Proposal<T>
|
||||||
|
|
||||||
@Suspendable
|
@Suspendable
|
||||||
private fun verifyTx(stx: SignedTransaction) {
|
private fun verifyTx(stx: SignedTransaction) {
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
package com.r3corda.protocols
|
package com.r3corda.protocols
|
||||||
|
|
||||||
import co.paralleluniverse.fibers.Suspendable
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import com.r3corda.core.contracts.*
|
import com.r3corda.core.contracts.ContractState
|
||||||
|
import com.r3corda.core.contracts.StateAndRef
|
||||||
|
import com.r3corda.core.contracts.StateRef
|
||||||
|
import com.r3corda.core.contracts.TransactionType
|
||||||
import com.r3corda.core.crypto.Party
|
import com.r3corda.core.crypto.Party
|
||||||
import com.r3corda.core.transactions.SignedTransaction
|
import com.r3corda.core.transactions.SignedTransaction
|
||||||
import com.r3corda.core.utilities.ProgressTracker
|
import com.r3corda.core.utilities.ProgressTracker
|
||||||
|
import com.r3corda.core.utilities.UntrustworthyData
|
||||||
|
import com.r3corda.protocols.NotaryChangeProtocol.Acceptor
|
||||||
|
import com.r3corda.protocols.NotaryChangeProtocol.Instigator
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,7 +68,8 @@ object NotaryChangeProtocol: AbstractStateReplacementProtocol<Party>() {
|
|||||||
* TODO: In more difficult cases this should call for human attention to manually verify and approve the proposal
|
* TODO: In more difficult cases this should call for human attention to manually verify and approve the proposal
|
||||||
*/
|
*/
|
||||||
@Suspendable
|
@Suspendable
|
||||||
override fun verifyProposal(proposal: AbstractStateReplacementProtocol.Proposal<Party>) {
|
override fun verifyProposal(maybeProposal: UntrustworthyData<AbstractStateReplacementProtocol.Proposal<Party>>): AbstractStateReplacementProtocol.Proposal<Party> {
|
||||||
|
return maybeProposal.validate { proposal ->
|
||||||
val newNotary = proposal.modification
|
val newNotary = proposal.modification
|
||||||
val isNotary = serviceHub.networkMapCache.notaryNodes.any { it.identity == newNotary }
|
val isNotary = serviceHub.networkMapCache.notaryNodes.any { it.identity == newNotary }
|
||||||
require(isNotary) { "The proposed node $newNotary does not run a Notary service " }
|
require(isNotary) { "The proposed node $newNotary does not run a Notary service " }
|
||||||
@ -74,6 +81,11 @@ object NotaryChangeProtocol: AbstractStateReplacementProtocol<Party>() {
|
|||||||
// An example requirement
|
// An example requirement
|
||||||
val blacklist = listOf("Evil Notary")
|
val blacklist = listOf("Evil Notary")
|
||||||
require(!blacklist.contains(newNotary.name)) { "The proposed new notary $newNotary is not trusted by the party" }
|
require(!blacklist.contains(newNotary.name)) { "The proposed new notary $newNotary is not trusted by the party" }
|
||||||
|
|
||||||
|
// TODO: Verify the type!
|
||||||
|
|
||||||
|
proposal
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user