22
33import co .paralleluniverse .fibers .Suspendable ;
44import com .google .common .collect .ImmutableList ;
5- import net .corda .core .crypto .keyrotation .crossprovider .PartyIdentityResolved ;
65import net .corda .core .crypto .keyrotation .crossprovider .PartyIdentityResolver ;
76import net .corda .samples .negotiation .contracts .ProposalAndTradeContract ;
87import net .corda .samples .negotiation .states .ProposalState ;
@@ -31,7 +30,6 @@ public class ModificationFlow {
3130 public static class Initiator extends FlowLogic <SignedTransaction >{
3231 private UniqueIdentifier proposalId ;
3332 private int newAmount ;
34- private ProgressTracker progressTracker = new ProgressTracker ();
3533
3634 public Initiator (UniqueIdentifier proposalId , int newAmount ) {
3735 this .proposalId = proposalId ;
@@ -44,9 +42,15 @@ public SignedTransaction call() throws FlowException {
4442 QueryCriteria .LinearStateQueryCriteria inputCriteria = new QueryCriteria .LinearStateQueryCriteria (null , ImmutableList .of (proposalId ), Vault .StateStatus .UNCONSUMED , null );
4543 StateAndRef inputStateAndRef = getServiceHub ().getVaultService ().queryBy (ProposalState .class , inputCriteria ).getStates ().get (0 );
4644 ProposalState input = (ProposalState ) inputStateAndRef .getState ().getData ();
47- Party proposerParty = PartyIdentityResolver .Companion .resolveToCurrentParty (input .getProposer (), getServiceHub ().getIdentityService ());
4845
4946 //Creating the output
47+ //
48+ // The proposerParty is retrieved from the state and must be resolved to its latest identity
49+ // before it can be compared with the party returned by `getOurIdentity`. Since the intent is not to
50+ // replace the old key with the new one in the output state, calling `resolveToCurrentParty` is sufficient.
51+ //
52+ // Comparing parties that both originate from states is safe without additional resolution.
53+ Party proposerParty = PartyIdentityResolver .Companion .resolveToCurrentParty (input .getProposer (), getServiceHub ().getIdentityService ());
5054 Party myPartyFromInput = (getOurIdentity ().equals (proposerParty )) ? input .getProposer () : input .getProposee ();
5155 Party counterpartyFromInput = (myPartyFromInput .equals (input .getProposer ()))? input .getProposee () : input .getProposer ();
5256 ProposalState output = new ProposalState (newAmount , input .getBuyer (),input .getSeller (), myPartyFromInput , counterpartyFromInput , input .getLinearId ());
@@ -66,6 +70,9 @@ public SignedTransaction call() throws FlowException {
6670 SignedTransaction partStx = getServiceHub ().signInitialTransaction (txBuilder );
6771
6872 //Gathering the counterparty's signatures
73+ //
74+ // The counterparty might be an old key, but the session will be initiated with the most up-to-date identity.
75+ // No need to use the resolved party in this case.
6976 FlowSession counterpartySession = initiateFlow (counterpartyFromInput );
7077 SignedTransaction fullyStx = subFlow (new CollectSignaturesFlow (partStx , ImmutableList .of (counterpartySession )));
7178
@@ -93,6 +100,13 @@ protected void checkTransaction(@NotNull SignedTransaction stx) throws FlowExcep
93100 try {
94101 LedgerTransaction ledgerTx = stx .toLedgerTransaction (getServiceHub (), false );
95102 ProposalState input = ledgerTx .inputsOfType (ProposalState .class ).get (0 );
103+
104+ // The counterparty session always provides the most up-to-date identity for the counterparty.
105+ //
106+ // Therefore, any party retrieved from a state must be resolved using `resolveToCurrentParty`.
107+ // While `resolveToCurrentParty` does not rely on a proof, it resolves the party to its latest valid identity.
108+ //
109+ // This ensures that equality checks behave as expected after key rotation.
96110 Party proposee = PartyIdentityResolver .Companion .resolveToCurrentParty (input .getProposee (), getServiceHub ().getIdentityService ());
97111 if (!proposee .equals (counterpartySession .getCounterparty ())){
98112 throw new FlowException ("Only the proposee can modify a proposal." );
0 commit comments