diff --git a/.ci/api-current.txt b/.ci/api-current.txt index 53601aaf1f..d31f2cbd19 100644 --- a/.ci/api-current.txt +++ b/.ci/api-current.txt @@ -1,4 +1,7 @@ @CordaSerializable +public interface net.corda.core.ClientRelevantError +## +@CordaSerializable public class net.corda.core.CordaException extends java.lang.Exception implements net.corda.core.CordaThrowable public () public (String) @@ -64,6 +67,12 @@ public interface net.corda.core.CordaThrowable public @interface net.corda.core.DoNotImplement ## public final class net.corda.core.Utils extends java.lang.Object + @NotNull + public static final net.corda.core.messaging.DataFeed doOnError(net.corda.core.messaging.DataFeed, kotlin.jvm.functions.Function1) + @NotNull + public static final net.corda.core.messaging.DataFeed mapErrors(net.corda.core.messaging.DataFeed, kotlin.jvm.functions.Function1) + @NotNull + public static final rx.Observable mapErrors(rx.Observable, kotlin.jvm.functions.Function1) @NotNull public static final net.corda.core.concurrent.CordaFuture toFuture(rx.Observable) @NotNull @@ -78,6 +87,7 @@ public final class net.corda.core.concurrent.ConcurrencyUtils extends java.lang. @NotNull public static final String shortCircuitedTaskFailedMessage = "Short-circuited task failed:" ## +@CordaSerializable public interface net.corda.core.concurrent.CordaFuture extends java.util.concurrent.Future public abstract void then(kotlin.jvm.functions.Function1, ? extends W>) @NotNull @@ -104,6 +114,7 @@ public final class net.corda.core.context.Actor extends java.lang.Object public int hashCode() @NotNull public static final net.corda.core.context.Actor service(String, net.corda.core.identity.CordaX500Name) + @NotNull public String toString() public static final net.corda.core.context.Actor$Companion Companion ## @@ -122,6 +133,7 @@ public static final class net.corda.core.context.Actor$Id extends java.lang.Obje @NotNull public final String getValue() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -135,6 +147,7 @@ public final class net.corda.core.context.AuthServiceId extends java.lang.Object @NotNull public final String getValue() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -178,6 +191,7 @@ public final class net.corda.core.context.InvocationContext extends java.lang.Ob public static final net.corda.core.context.InvocationContext service(String, net.corda.core.identity.CordaX500Name, net.corda.core.context.Trace, net.corda.core.context.Trace) @NotNull public static final net.corda.core.context.InvocationContext shell(net.corda.core.context.Trace, net.corda.core.context.Trace) + @NotNull public String toString() public static final net.corda.core.context.InvocationContext$Companion Companion ## @@ -213,17 +227,23 @@ public static final class net.corda.core.context.InvocationOrigin$Peer extends n public int hashCode() @NotNull public java.security.Principal principal() + @NotNull public String toString() ## @CordaSerializable public static final class net.corda.core.context.InvocationOrigin$RPC extends net.corda.core.context.InvocationOrigin public (net.corda.core.context.Actor) @NotNull + public final net.corda.core.context.Actor component1() + @NotNull public final net.corda.core.context.InvocationOrigin$RPC copy(net.corda.core.context.Actor) public boolean equals(Object) + @NotNull + public final net.corda.core.context.Actor getActor() public int hashCode() @NotNull public java.security.Principal principal() + @NotNull public String toString() ## @CordaSerializable @@ -239,6 +259,7 @@ public static final class net.corda.core.context.InvocationOrigin$Scheduled exte public int hashCode() @NotNull public java.security.Principal principal() + @NotNull public String toString() ## @CordaSerializable @@ -258,6 +279,7 @@ public static final class net.corda.core.context.InvocationOrigin$Service extend public int hashCode() @NotNull public java.security.Principal principal() + @NotNull public String toString() ## @CordaSerializable @@ -283,6 +305,7 @@ public final class net.corda.core.context.Trace extends java.lang.Object public int hashCode() @NotNull public static final net.corda.core.context.Trace newInstance(net.corda.core.context.Trace$InvocationId, net.corda.core.context.Trace$SessionId) + @NotNull public String toString() public static final net.corda.core.context.Trace$Companion Companion ## @@ -315,6 +338,7 @@ public static final class net.corda.core.context.Trace$SessionId$Companion exten @DoNotImplement @CordaSerializable public final class net.corda.core.contracts.AlwaysAcceptAttachmentConstraint extends java.lang.Object implements net.corda.core.contracts.AttachmentConstraint + public boolean canBeTransitionedFrom(net.corda.core.contracts.AttachmentConstraint, net.corda.core.contracts.ContractAttachment) public boolean isSatisfiedBy(net.corda.core.contracts.Attachment) public static final net.corda.core.contracts.AlwaysAcceptAttachmentConstraint INSTANCE ## @@ -441,8 +465,14 @@ public interface net.corda.core.contracts.Attachment extends net.corda.core.cont @DoNotImplement @CordaSerializable public interface net.corda.core.contracts.AttachmentConstraint + public abstract boolean canBeTransitionedFrom(net.corda.core.contracts.AttachmentConstraint, net.corda.core.contracts.ContractAttachment) public abstract boolean isSatisfiedBy(net.corda.core.contracts.Attachment) ## +public final class net.corda.core.contracts.AttachmentConstraintKt extends java.lang.Object + public static final void checkConstraintValidity(net.corda.core.contracts.TransactionState) + public static final boolean contractHasAutomaticConstraintPropagation(String, ClassLoader) + public static final void warnContractWithoutConstraintPropagation(String, ClassLoader) +## @CordaSerializable public final class net.corda.core.contracts.AttachmentResolutionException extends net.corda.core.flows.FlowException public (net.corda.core.crypto.SecureHash) @@ -452,12 +482,24 @@ public final class net.corda.core.contracts.AttachmentResolutionException extend @DoNotImplement @CordaSerializable public final class net.corda.core.contracts.AutomaticHashConstraint extends java.lang.Object implements net.corda.core.contracts.AttachmentConstraint + public boolean canBeTransitionedFrom(net.corda.core.contracts.AttachmentConstraint, net.corda.core.contracts.ContractAttachment) public boolean isSatisfiedBy(net.corda.core.contracts.Attachment) public static final net.corda.core.contracts.AutomaticHashConstraint INSTANCE ## +@DoNotImplement +@CordaSerializable +public final class net.corda.core.contracts.AutomaticPlaceholderConstraint extends java.lang.Object implements net.corda.core.contracts.AttachmentConstraint + public boolean canBeTransitionedFrom(net.corda.core.contracts.AttachmentConstraint, net.corda.core.contracts.ContractAttachment) + public boolean isSatisfiedBy(net.corda.core.contracts.Attachment) + public static final net.corda.core.contracts.AutomaticPlaceholderConstraint INSTANCE +## public @interface net.corda.core.contracts.BelongsToContract public abstract Class value() ## +public final class net.corda.core.contracts.BelongsToContractKt extends java.lang.Object + @Nullable + public static final String getRequiredContractClassName(net.corda.core.contracts.ContractState) +## @CordaSerializable public final class net.corda.core.contracts.Command extends java.lang.Object public (T, java.security.PublicKey) @@ -491,6 +533,7 @@ public final class net.corda.core.contracts.CommandAndState extends java.lang.Ob @NotNull public final net.corda.core.contracts.OwnableState getOwnableState() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -515,6 +558,7 @@ public final class net.corda.core.contracts.CommandWithParties extends java.lang @NotNull public final T getValue() public int hashCode() + @NotNull public String toString() ## public final class net.corda.core.contracts.ComponentGroupEnum extends java.lang.Enum @@ -531,6 +575,7 @@ public final class net.corda.core.contracts.ContractAttachment extends java.lang public (net.corda.core.contracts.Attachment, String) public (net.corda.core.contracts.Attachment, String, java.util.Set) public (net.corda.core.contracts.Attachment, String, java.util.Set, String) + public (net.corda.core.contracts.Attachment, String, java.util.Set, String, java.util.List) @NotNull public final java.util.Set getAdditionalContracts() @NotNull @@ -569,6 +614,7 @@ public final class net.corda.core.contracts.ContractsDSL extends java.lang.Objec public interface net.corda.core.contracts.FungibleAsset extends net.corda.core.contracts.FungibleState, net.corda.core.contracts.OwnableState @NotNull public abstract net.corda.core.contracts.Amount> getAmount() + @SerializableCalculatedProperty @NotNull public abstract java.util.Collection getExitKeys() @NotNull @@ -583,6 +629,7 @@ public interface net.corda.core.contracts.FungibleState extends net.corda.core.c @CordaSerializable public final class net.corda.core.contracts.HashAttachmentConstraint extends java.lang.Object implements net.corda.core.contracts.AttachmentConstraint public (net.corda.core.crypto.SecureHash) + public boolean canBeTransitionedFrom(net.corda.core.contracts.AttachmentConstraint, net.corda.core.contracts.ContractAttachment) @NotNull public final net.corda.core.crypto.SecureHash component1() @NotNull @@ -592,6 +639,7 @@ public final class net.corda.core.contracts.HashAttachmentConstraint extends jav public final net.corda.core.crypto.SecureHash getAttachmentId() public int hashCode() public boolean isSatisfiedBy(net.corda.core.contracts.Attachment) + @NotNull public String toString() ## @CordaSerializable @@ -647,6 +695,8 @@ public interface net.corda.core.contracts.NamedByHash @NotNull public abstract net.corda.core.crypto.SecureHash getId() ## +public @interface net.corda.core.contracts.NoConstraintPropagation +## @CordaSerializable public interface net.corda.core.contracts.OwnableState extends net.corda.core.contracts.ContractState @NotNull @@ -677,6 +727,19 @@ public final class net.corda.core.contracts.PrivacySalt extends net.corda.core.u public () public (byte[]) ## +public final class net.corda.core.contracts.ReferencedStateAndRef extends java.lang.Object + public (net.corda.core.contracts.StateAndRef) + @NotNull + public final net.corda.core.contracts.StateAndRef component1() + @NotNull + public final net.corda.core.contracts.ReferencedStateAndRef copy(net.corda.core.contracts.StateAndRef) + public boolean equals(Object) + @NotNull + public final net.corda.core.contracts.StateAndRef getStateAndRef() + public int hashCode() + @NotNull + public String toString() +## public final class net.corda.core.contracts.Requirements extends java.lang.Object public final void using(String, boolean) public static final net.corda.core.contracts.Requirements INSTANCE @@ -704,6 +767,7 @@ public final class net.corda.core.contracts.ScheduledActivity extends java.lang. @NotNull public java.time.Instant getScheduledAt() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -721,6 +785,24 @@ public final class net.corda.core.contracts.ScheduledStateRef extends java.lang. @NotNull public java.time.Instant getScheduledAt() public int hashCode() + @NotNull + public String toString() +## +@DoNotImplement +@CordaSerializable +public final class net.corda.core.contracts.SignatureAttachmentConstraint extends java.lang.Object implements net.corda.core.contracts.AttachmentConstraint + public (java.security.PublicKey) + public boolean canBeTransitionedFrom(net.corda.core.contracts.AttachmentConstraint, net.corda.core.contracts.ContractAttachment) + @NotNull + public final java.security.PublicKey component1() + @NotNull + public final net.corda.core.contracts.SignatureAttachmentConstraint copy(java.security.PublicKey) + public boolean equals(Object) + @NotNull + public final java.security.PublicKey getKey() + public int hashCode() + public boolean isSatisfiedBy(net.corda.core.contracts.Attachment) + @NotNull public String toString() ## public final class net.corda.core.contracts.SourceAndAmount extends java.lang.Object @@ -741,6 +823,7 @@ public final class net.corda.core.contracts.SourceAndAmount extends java.lang.Ob @NotNull public final P getSource() public int hashCode() + @NotNull public String toString() ## public final class net.corda.core.contracts.StateAndContract extends java.lang.Object @@ -757,6 +840,7 @@ public final class net.corda.core.contracts.StateAndContract extends java.lang.O @NotNull public final net.corda.core.contracts.ContractState getState() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -774,6 +858,9 @@ public final class net.corda.core.contracts.StateAndRef extends java.lang.Object @NotNull public final net.corda.core.contracts.TransactionState getState() public int hashCode() + @NotNull + public final net.corda.core.contracts.ReferencedStateAndRef referenced() + @NotNull public String toString() ## @CordaSerializable @@ -873,6 +960,7 @@ public final class net.corda.core.contracts.TransactionState extends java.lang.O public (T, String, net.corda.core.identity.Party) public (T, String, net.corda.core.identity.Party, Integer) public (T, String, net.corda.core.identity.Party, Integer, net.corda.core.contracts.AttachmentConstraint) + public (T, net.corda.core.identity.Party) @NotNull public final T component1() @NotNull @@ -897,12 +985,15 @@ public final class net.corda.core.contracts.TransactionState extends java.lang.O @NotNull public final net.corda.core.identity.Party getNotary() public int hashCode() + @NotNull public String toString() + public static final net.corda.core.contracts.TransactionState$Companion Companion ## public final class net.corda.core.contracts.TransactionStateKt extends java.lang.Object ## @CordaSerializable public abstract class net.corda.core.contracts.TransactionVerificationException extends net.corda.core.flows.FlowException + public (net.corda.core.crypto.SecureHash, String, Throwable) @NotNull public final net.corda.core.crypto.SecureHash getTxId() ## @@ -913,6 +1004,20 @@ public static final class net.corda.core.contracts.TransactionVerificationExcept public final String getContractClass() ## @CordaSerializable +public static final class net.corda.core.contracts.TransactionVerificationException$ConstraintPropagationRejection extends net.corda.core.contracts.TransactionVerificationException + public (net.corda.core.crypto.SecureHash, String, net.corda.core.contracts.AttachmentConstraint, net.corda.core.contracts.AttachmentConstraint) + @NotNull + public final String getContractClass() +## +@CordaSerializable +public static final class net.corda.core.contracts.TransactionVerificationException$ContractAttachmentNotSignedByPackageOwnerException extends net.corda.core.contracts.TransactionVerificationException + public (net.corda.core.crypto.SecureHash, net.corda.core.crypto.SecureHash, String) + @NotNull + public final net.corda.core.crypto.SecureHash getAttachmentHash() + @NotNull + public final String getContractClass() +## +@CordaSerializable public static final class net.corda.core.contracts.TransactionVerificationException$ContractConstraintRejection extends net.corda.core.contracts.TransactionVerificationException public (net.corda.core.crypto.SecureHash, String) @NotNull @@ -972,6 +1077,10 @@ public static final class net.corda.core.contracts.TransactionVerificationExcept public final java.util.List getMissing() ## @CordaSerializable +public static final class net.corda.core.contracts.TransactionVerificationException$TransactionDuplicateEncumbranceException extends net.corda.core.contracts.TransactionVerificationException + public (net.corda.core.crypto.SecureHash, int) +## +@CordaSerializable public static final class net.corda.core.contracts.TransactionVerificationException$TransactionMissingEncumbranceException extends net.corda.core.contracts.TransactionVerificationException public (net.corda.core.crypto.SecureHash, int, net.corda.core.contracts.TransactionVerificationException$Direction) @NotNull @@ -979,6 +1088,14 @@ public static final class net.corda.core.contracts.TransactionVerificationExcept public final int getMissing() ## @CordaSerializable +public static final class net.corda.core.contracts.TransactionVerificationException$TransactionNonMatchingEncumbranceException extends net.corda.core.contracts.TransactionVerificationException + public (net.corda.core.crypto.SecureHash, java.util.Collection) +## +@CordaSerializable +public static final class net.corda.core.contracts.TransactionVerificationException$TransactionNotaryMismatchEncumbranceException extends net.corda.core.contracts.TransactionVerificationException + public (net.corda.core.crypto.SecureHash, int, int, net.corda.core.identity.Party, net.corda.core.identity.Party) +## +@CordaSerializable public abstract class net.corda.core.contracts.TypeOnlyCommandData extends java.lang.Object implements net.corda.core.contracts.CommandData public () public boolean equals(Object) @@ -987,6 +1104,7 @@ public abstract class net.corda.core.contracts.TypeOnlyCommandData extends java. @CordaSerializable public final class net.corda.core.contracts.UniqueIdentifier extends java.lang.Object implements java.lang.Comparable public () + public (String) public (String, java.util.UUID) public int compareTo(net.corda.core.contracts.UniqueIdentifier) @Nullable @@ -1024,11 +1142,14 @@ public interface net.corda.core.contracts.UpgradedContractWithLegacyConstraint e @DoNotImplement @CordaSerializable public final class net.corda.core.contracts.WhitelistedByZoneAttachmentConstraint extends java.lang.Object implements net.corda.core.contracts.AttachmentConstraint + public boolean canBeTransitionedFrom(net.corda.core.contracts.AttachmentConstraint, net.corda.core.contracts.ContractAttachment) public boolean isSatisfiedBy(net.corda.core.contracts.Attachment) public static final net.corda.core.contracts.WhitelistedByZoneAttachmentConstraint INSTANCE ## @DoNotImplement public interface net.corda.core.cordapp.Cordapp + @NotNull + public abstract java.util.List>> getAllFlows() @NotNull public abstract java.util.List getContractClassNames() @NotNull @@ -1038,9 +1159,13 @@ public interface net.corda.core.cordapp.Cordapp @NotNull public abstract java.util.List>> getInitiatedFlows() @NotNull + public abstract net.corda.core.crypto.SecureHash$SHA256 getJarHash() + @NotNull public abstract java.net.URL getJarPath() @NotNull public abstract String getName() + @Nullable + public abstract Class getNotaryService() @NotNull public abstract java.util.List>> getRpcFlows() @NotNull @@ -1054,6 +1179,24 @@ public interface net.corda.core.cordapp.Cordapp @NotNull public abstract java.util.List> getServices() ## +@DoNotImplement +public interface net.corda.core.cordapp.CordappConfig + public abstract boolean exists(String) + @NotNull + public abstract Object get(String) + public abstract boolean getBoolean(String) + public abstract double getDouble(String) + public abstract float getFloat(String) + public abstract int getInt(String) + public abstract long getLong(String) + @NotNull + public abstract Number getNumber(String) + @NotNull + public abstract String getString(String) +## +public final class net.corda.core.cordapp.CordappConfigException extends java.lang.Exception + public (String, Throwable) +## public final class net.corda.core.cordapp.CordappContext extends java.lang.Object public (net.corda.core.cordapp.Cordapp, net.corda.core.crypto.SecureHash, ClassLoader, net.corda.core.cordapp.CordappConfig) @Nullable @@ -1061,6 +1204,8 @@ public final class net.corda.core.cordapp.CordappContext extends java.lang.Objec @NotNull public final ClassLoader getClassLoader() @NotNull + public final net.corda.core.cordapp.CordappConfig getConfig() + @NotNull public final net.corda.core.cordapp.Cordapp getCordapp() ## @DoNotImplement @@ -1190,6 +1335,7 @@ public static final class net.corda.core.crypto.CompositeSignature$State extends @NotNull public final net.corda.core.crypto.CompositeKey getVerifyKey() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -1203,6 +1349,7 @@ public final class net.corda.core.crypto.CompositeSignaturesWithKeys extends jav @NotNull public final java.util.List getSigs() public int hashCode() + @NotNull public String toString() public static final net.corda.core.crypto.CompositeSignaturesWithKeys$Companion Companion ## @@ -1225,6 +1372,10 @@ public final class net.corda.core.crypto.CordaSecurityProvider extends java.secu ## public static final class net.corda.core.crypto.CordaSecurityProvider$Companion extends java.lang.Object ## +public final class net.corda.core.crypto.CordaSecurityProviderKt extends java.lang.Object + @NotNull + public static final String CORDA_SECURE_RANDOM_ALGORITHM = "CordaPRNG" +## public final class net.corda.core.crypto.Crypto extends java.lang.Object @NotNull public static final java.security.PrivateKey decodePrivateKey(String, byte[]) @@ -1281,6 +1432,7 @@ public final class net.corda.core.crypto.Crypto extends java.lang.Object public static final boolean isValid(net.corda.core.crypto.SecureHash, net.corda.core.crypto.TransactionSignature) public static final boolean isValid(net.corda.core.crypto.SignatureScheme, java.security.PublicKey, byte[], byte[]) public static final boolean publicKeyOnCurve(net.corda.core.crypto.SignatureScheme, java.security.PublicKey) + public static final void registerProviders() @NotNull public static final java.util.List supportedSignatureSchemes() @NotNull @@ -1289,6 +1441,7 @@ public final class net.corda.core.crypto.Crypto extends java.lang.Object public static final java.security.PublicKey toSupportedPublicKey(java.security.PublicKey) @NotNull public static final java.security.PublicKey toSupportedPublicKey(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo) + public static final boolean validatePublicKey(java.security.PublicKey) @NotNull public static final net.corda.core.crypto.SignatureScheme COMPOSITE_KEY @NotNull @@ -1326,7 +1479,10 @@ public final class net.corda.core.crypto.CryptoUtils extends java.lang.Object @NotNull public static final java.security.KeyPair generateKeyPair() @NotNull + public static final java.util.Set getBlacklistedCrlEndpoints() + @NotNull public static final java.util.Set getKeys(java.security.PublicKey) + public static final boolean isCRLDistributionPointBlacklisted(java.util.List) public static final boolean isFulfilledBy(java.security.PublicKey, Iterable) public static final boolean isFulfilledBy(java.security.PublicKey, java.security.PublicKey) public static final boolean isValid(java.security.PublicKey, byte[], net.corda.core.crypto.DigitalSignature) @@ -1353,6 +1509,13 @@ public final class net.corda.core.crypto.CryptoUtils extends java.lang.Object public static final boolean verify(java.security.PublicKey, byte[], net.corda.core.crypto.DigitalSignature) public static final boolean verify(java.security.PublicKey, byte[], byte[]) ## +public final class net.corda.core.crypto.DelegatingSecureRandomSpi extends java.security.SecureRandomSpi + public (kotlin.jvm.functions.Function0) + @Nullable + protected byte[] engineGenerateSeed(int) + protected void engineNextBytes(byte[]) + protected void engineSetSeed(byte[]) +## @CordaSerializable public class net.corda.core.crypto.DigitalSignature extends net.corda.core.utilities.OpaqueBytes public (byte[]) @@ -1368,6 +1531,9 @@ public static class net.corda.core.crypto.DigitalSignature$WithKey extends net.c @NotNull public final net.corda.core.crypto.DigitalSignature withoutKey() ## +public final class net.corda.core.crypto.DummySecureRandom extends java.security.SecureRandom + public static final net.corda.core.crypto.DummySecureRandom INSTANCE +## public abstract class net.corda.core.crypto.MerkleTree extends java.lang.Object @NotNull public abstract net.corda.core.crypto.SecureHash getHash() @@ -1387,6 +1553,7 @@ public static final class net.corda.core.crypto.MerkleTree$Leaf extends net.cord @NotNull public net.corda.core.crypto.SecureHash getHash() public int hashCode() + @NotNull public String toString() ## public static final class net.corda.core.crypto.MerkleTree$Node extends net.corda.core.crypto.MerkleTree @@ -1407,6 +1574,7 @@ public static final class net.corda.core.crypto.MerkleTree$Node extends net.cord @NotNull public final net.corda.core.crypto.MerkleTree getRight() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -1463,6 +1631,7 @@ public static final class net.corda.core.crypto.PartialMerkleTree$PartialTree$In @NotNull public final net.corda.core.crypto.SecureHash getHash() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -1476,6 +1645,7 @@ public static final class net.corda.core.crypto.PartialMerkleTree$PartialTree$Le @NotNull public final net.corda.core.crypto.SecureHash getHash() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -1493,6 +1663,7 @@ public static final class net.corda.core.crypto.PartialMerkleTree$PartialTree$No @NotNull public final net.corda.core.crypto.PartialMerkleTree$PartialTree getRight() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -1514,6 +1685,10 @@ public abstract class net.corda.core.crypto.SecureHash extends net.corda.core.ut @NotNull public String toString() public static final net.corda.core.crypto.SecureHash$Companion Companion + @NotNull + public static final net.corda.core.crypto.SecureHash$SHA256 allOnesHash + @NotNull + public static final net.corda.core.crypto.SecureHash$SHA256 zeroHash ## public static final class net.corda.core.crypto.SecureHash$Companion extends java.lang.Object @NotNull @@ -1556,6 +1731,7 @@ public final class net.corda.core.crypto.SignableData extends java.lang.Object @NotNull public final net.corda.core.crypto.SecureHash getTxId() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -1569,6 +1745,7 @@ public final class net.corda.core.crypto.SignatureMetadata extends java.lang.Obj public final int getPlatformVersion() public final int getSchemeNumberID() public int hashCode() + @NotNull public String toString() ## public final class net.corda.core.crypto.SignatureScheme extends java.lang.Object @@ -1615,6 +1792,7 @@ public final class net.corda.core.crypto.SignatureScheme extends java.lang.Objec @NotNull public final org.bouncycastle.asn1.x509.AlgorithmIdentifier getSignatureOID() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -1712,6 +1890,7 @@ public static final class net.corda.core.flows.AbstractStateReplacementFlow$Prop @NotNull public final net.corda.core.contracts.StateRef getStateRef() public int hashCode() + @NotNull public String toString() ## public static final class net.corda.core.flows.AbstractStateReplacementFlow$UpgradeTx extends java.lang.Object @@ -1724,6 +1903,7 @@ public static final class net.corda.core.flows.AbstractStateReplacementFlow$Upgr @NotNull public final net.corda.core.transactions.SignedTransaction getStx() public int hashCode() + @NotNull public String toString() ## @Suspendable @@ -1819,8 +1999,11 @@ public class net.corda.core.flows.DataVendingFlow extends net.corda.core.flows.F @InitiatingFlow public final class net.corda.core.flows.FinalityFlow extends net.corda.core.flows.FlowLogic public (net.corda.core.transactions.SignedTransaction) + public (net.corda.core.transactions.SignedTransaction, java.util.Collection) + public (net.corda.core.transactions.SignedTransaction, java.util.Collection, net.corda.core.utilities.ProgressTracker) public (net.corda.core.transactions.SignedTransaction, java.util.Set) public (net.corda.core.transactions.SignedTransaction, java.util.Set, net.corda.core.utilities.ProgressTracker) + public (net.corda.core.transactions.SignedTransaction, net.corda.core.flows.FlowSession, net.corda.core.flows.FlowSession...) public (net.corda.core.transactions.SignedTransaction, net.corda.core.utilities.ProgressTracker) @Suspendable @NotNull @@ -1852,7 +2035,13 @@ public class net.corda.core.flows.FlowException extends net.corda.core.CordaExce public () public (String) public (String, Throwable) + public (String, Throwable, Long) public (Throwable) + @Nullable + public Long getErrorId() + @Nullable + public final Long getOriginalErrorId() + public final void setOriginalErrorId(Long) ## @CordaSerializable public final class net.corda.core.flows.FlowInfo extends java.lang.Object @@ -1867,6 +2056,7 @@ public final class net.corda.core.flows.FlowInfo extends java.lang.Object public final String getAppName() public final int getFlowVersion() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -1887,6 +2077,7 @@ public static final class net.corda.core.flows.FlowInitiator$Peer extends net.co @NotNull public final net.corda.core.identity.Party getParty() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -1902,6 +2093,7 @@ public static final class net.corda.core.flows.FlowInitiator$RPC extends net.cor @NotNull public final String getUsername() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -1917,6 +2109,7 @@ public static final class net.corda.core.flows.FlowInitiator$Scheduled extends n @NotNull public final net.corda.core.contracts.ScheduledStateRef getScheduledState() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -1932,6 +2125,7 @@ public static final class net.corda.core.flows.FlowInitiator$Service extends net @NotNull public final String getServiceClassName() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -1978,7 +2172,13 @@ public abstract class net.corda.core.flows.FlowLogic extends java.lang.Object public java.util.List> receiveAll(Class, java.util.List) @Suspendable @NotNull + public java.util.List> receiveAll(Class, java.util.List, boolean) + @Suspendable + @NotNull public java.util.Map> receiveAllMap(java.util.Map>) + @Suspendable + @NotNull + public java.util.Map> receiveAllMap(java.util.Map>, boolean) public final void recordAuditEvent(String, String, java.util.Map) @Suspendable public void send(net.corda.core.identity.Party, Object) @@ -1988,6 +2188,8 @@ public abstract class net.corda.core.flows.FlowLogic extends java.lang.Object @Suspendable public static final void sleep(java.time.Duration) @Suspendable + public static final void sleep(java.time.Duration, boolean) + @Suspendable public R subFlow(net.corda.core.flows.FlowLogic) @Nullable public final net.corda.core.messaging.DataFeed track() @@ -2001,6 +2203,8 @@ public abstract class net.corda.core.flows.FlowLogic extends java.lang.Object @Suspendable @NotNull public final net.corda.core.transactions.SignedTransaction waitForLedgerCommit(net.corda.core.crypto.SecureHash, boolean) + @Suspendable + public final void waitForStateConsumption(java.util.Set) public static final net.corda.core.flows.FlowLogic$Companion Companion ## public static final class net.corda.core.flows.FlowLogic$Companion extends java.lang.Object @@ -2008,6 +2212,8 @@ public static final class net.corda.core.flows.FlowLogic$Companion extends java. public final net.corda.core.flows.FlowLogic getCurrentTopLevel() @Suspendable public final void sleep(java.time.Duration) + @Suspendable + public final void sleep(java.time.Duration, boolean) ## @DoNotImplement @CordaSerializable @@ -2068,6 +2274,7 @@ public final class net.corda.core.flows.FlowStackSnapshot extends java.lang.Obje @NotNull public final java.time.Instant getTime() public int hashCode() + @NotNull public String toString() ## public static final class net.corda.core.flows.FlowStackSnapshot$Frame extends java.lang.Object @@ -2087,6 +2294,10 @@ public static final class net.corda.core.flows.FlowStackSnapshot$Frame extends j @NotNull public String toString() ## +public interface net.corda.core.flows.IdentifiableException + @Nullable + public Long getErrorId() +## @CordaSerializable public final class net.corda.core.flows.IllegalFlowLogicException extends java.lang.IllegalArgumentException public (Class, String) @@ -2119,6 +2330,7 @@ public final class net.corda.core.flows.NotarisationPayload extends java.lang.Ob @NotNull public final Object getTransaction() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -2145,6 +2357,7 @@ public final class net.corda.core.flows.NotarisationRequestSignature extends jav public final net.corda.core.crypto.DigitalSignature$WithKey getDigitalSignature() public final int getPlatformVersion() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -2158,6 +2371,7 @@ public final class net.corda.core.flows.NotarisationResponse extends java.lang.O @NotNull public final java.util.List getSignatures() public int hashCode() + @NotNull public String toString() ## @InitiatingFlow @@ -2298,19 +2512,39 @@ public static final class net.corda.core.flows.NotaryFlow$Client$Companion$REQUE public static final class net.corda.core.flows.NotaryFlow$Client$Companion$VALIDATING extends net.corda.core.utilities.ProgressTracker$Step public static final net.corda.core.flows.NotaryFlow$Client$Companion$VALIDATING INSTANCE ## +public final class net.corda.core.flows.ReceiveFinalityFlow extends net.corda.core.flows.FlowLogic + public (net.corda.core.flows.FlowSession) + public (net.corda.core.flows.FlowSession, net.corda.core.crypto.SecureHash) + public (net.corda.core.flows.FlowSession, net.corda.core.crypto.SecureHash, net.corda.core.node.StatesToRecord) + @Suspendable + @NotNull + public net.corda.core.transactions.SignedTransaction call() + @Nullable + public final net.corda.core.crypto.SecureHash getExpectedTxId() + @NotNull + public final net.corda.core.flows.FlowSession getOtherSideSession() + @NotNull + public final net.corda.core.node.StatesToRecord getStatesToRecord() +## public final class net.corda.core.flows.ReceiveStateAndRefFlow extends net.corda.core.flows.FlowLogic public (net.corda.core.flows.FlowSession) @Suspendable @NotNull public java.util.List> call() ## -public final class net.corda.core.flows.ReceiveTransactionFlow extends net.corda.core.flows.FlowLogic +public class net.corda.core.flows.ReceiveTransactionFlow extends net.corda.core.flows.FlowLogic public (net.corda.core.flows.FlowSession) public (net.corda.core.flows.FlowSession, boolean) public (net.corda.core.flows.FlowSession, boolean, net.corda.core.node.StatesToRecord) @Suspendable @NotNull public net.corda.core.transactions.SignedTransaction call() + @Suspendable + protected void checkBeforeRecording(net.corda.core.transactions.SignedTransaction) +## +@CordaSerializable +public final class net.corda.core.flows.RetrieveAnyTransactionPayload extends java.util.ArrayList + public static final net.corda.core.flows.RetrieveAnyTransactionPayload INSTANCE ## public @interface net.corda.core.flows.SchedulableFlow ## @@ -2321,6 +2555,7 @@ public class net.corda.core.flows.SendTransactionFlow extends net.corda.core.flo public (net.corda.core.flows.FlowSession, net.corda.core.transactions.SignedTransaction) ## public abstract class net.corda.core.flows.SignTransactionFlow extends net.corda.core.flows.FlowLogic + public (net.corda.core.flows.FlowSession) public (net.corda.core.flows.FlowSession, net.corda.core.utilities.ProgressTracker) @Suspendable @NotNull @@ -2361,6 +2596,7 @@ public final class net.corda.core.flows.StackFrameDataToken extends java.lang.Ob @NotNull public final String getClassName() public int hashCode() + @NotNull public String toString() ## public @interface net.corda.core.flows.StartableByRPC @@ -2370,17 +2606,31 @@ public @interface net.corda.core.flows.StartableByService @CordaSerializable public final class net.corda.core.flows.StateConsumptionDetails extends java.lang.Object public (net.corda.core.crypto.SecureHash) + public (net.corda.core.crypto.SecureHash, net.corda.core.flows.StateConsumptionDetails$ConsumedStateType) @NotNull public final net.corda.core.crypto.SecureHash component1() @NotNull + public final net.corda.core.flows.StateConsumptionDetails$ConsumedStateType component2() + @NotNull public final net.corda.core.flows.StateConsumptionDetails copy(net.corda.core.crypto.SecureHash) + @NotNull + public final net.corda.core.flows.StateConsumptionDetails copy(net.corda.core.crypto.SecureHash, net.corda.core.flows.StateConsumptionDetails$ConsumedStateType) public boolean equals(Object) @NotNull public final net.corda.core.crypto.SecureHash getHashOfTransactionId() + @NotNull + public final net.corda.core.flows.StateConsumptionDetails$ConsumedStateType getType() public int hashCode() + @NotNull public String toString() ## @CordaSerializable +public static final class net.corda.core.flows.StateConsumptionDetails$ConsumedStateType extends java.lang.Enum + protected () + public static net.corda.core.flows.StateConsumptionDetails$ConsumedStateType valueOf(String) + public static net.corda.core.flows.StateConsumptionDetails$ConsumedStateType[] values() +## +@CordaSerializable public final class net.corda.core.flows.StateMachineRunId extends java.lang.Object public (java.util.UUID) @NotNull @@ -2409,6 +2659,68 @@ public class net.corda.core.flows.StateReplacementException extends net.corda.co public final class net.corda.core.flows.UnexpectedFlowEndException extends net.corda.core.CordaRuntimeException implements net.corda.core.flows.IdentifiableException public (String) public (String, Throwable) + public (String, Throwable, Long) + @Nullable + public Long getErrorId() + @Nullable + public final Long getOriginalErrorId() +## +public final class net.corda.core.flows.WithReferencedStatesFlow extends net.corda.core.flows.FlowLogic + public (net.corda.core.flows.FlowLogic, net.corda.core.utilities.ProgressTracker) + @Suspendable + @NotNull + public T call() + @NotNull + public final net.corda.core.flows.FlowLogic getFlowLogic() + @NotNull + public net.corda.core.utilities.ProgressTracker getProgressTracker() + @NotNull + public static final net.corda.core.utilities.ProgressTracker tracker() + public static final net.corda.core.flows.WithReferencedStatesFlow$Companion Companion +## +public static final class net.corda.core.flows.WithReferencedStatesFlow$Companion extends java.lang.Object + @NotNull + public final org.slf4j.Logger getLogger() + @NotNull + public final net.corda.core.utilities.ProgressTracker tracker() +## +@CordaSerializable +public static final class net.corda.core.flows.WithReferencedStatesFlow$Companion$ATTEMPT extends net.corda.core.utilities.ProgressTracker$Step + public static final net.corda.core.flows.WithReferencedStatesFlow$Companion$ATTEMPT INSTANCE +## +@CordaSerializable +public static final class net.corda.core.flows.WithReferencedStatesFlow$Companion$RETRYING extends net.corda.core.utilities.ProgressTracker$Step + public static final net.corda.core.flows.WithReferencedStatesFlow$Companion$RETRYING INSTANCE +## +@CordaSerializable +public static final class net.corda.core.flows.WithReferencedStatesFlow$Companion$SUCCESS extends net.corda.core.utilities.ProgressTracker$Step + public static final net.corda.core.flows.WithReferencedStatesFlow$Companion$SUCCESS INSTANCE +## +public static final class net.corda.core.flows.WithReferencedStatesFlow$FlowResult$Conflict extends net.corda.core.flows.WithReferencedStatesFlow$FlowResult + public (java.util.Set) + @NotNull + public final java.util.Set component1() + @NotNull + public final net.corda.core.flows.WithReferencedStatesFlow$FlowResult$Conflict copy(java.util.Set) + public boolean equals(Object) + @NotNull + public final java.util.Set getStateRefs() + public int hashCode() + @NotNull + public String toString() +## +public static final class net.corda.core.flows.WithReferencedStatesFlow$FlowResult$Success extends net.corda.core.flows.WithReferencedStatesFlow$FlowResult + public (T) + @NotNull + public final T component1() + @NotNull + public final net.corda.core.flows.WithReferencedStatesFlow$FlowResult$Success copy(T) + public boolean equals(Object) + @NotNull + public final T getValue() + public int hashCode() + @NotNull + public String toString() ## @DoNotImplement @CordaSerializable @@ -2566,6 +2878,7 @@ public final class net.corda.core.messaging.ClientRpcSslOptions extends java.lan @NotNull public final String getTrustStoreProvider() public int hashCode() + @NotNull public String toString() ## @DoNotImplement @@ -2577,6 +2890,8 @@ public interface net.corda.core.messaging.CordaRPCOps extends net.corda.core.mes @NotNull public abstract java.time.Instant currentNodeTime() @NotNull + public abstract net.corda.core.node.NetworkParameters getNetworkParameters() + @NotNull public abstract Iterable getVaultTransactionNotes(net.corda.core.crypto.SecureHash) @RPCReturnsObservables @NotNull @@ -2584,6 +2899,8 @@ public interface net.corda.core.messaging.CordaRPCOps extends net.corda.core.mes @NotNull public abstract java.util.List internalVerifiedTransactionsSnapshot() public abstract boolean isFlowsDrainingModeEnabled() + public abstract boolean isWaitingForShutdown() + public abstract boolean killFlow(net.corda.core.flows.StateMachineRunId) @RPCReturnsObservables @NotNull public abstract net.corda.core.messaging.DataFeed, net.corda.core.node.services.NetworkMapCache$MapChange> networkMapFeed() @@ -2608,9 +2925,11 @@ public interface net.corda.core.messaging.CordaRPCOps extends net.corda.core.mes public abstract net.corda.core.identity.Party partyFromKey(java.security.PublicKey) @NotNull public abstract java.util.List queryAttachments(net.corda.core.node.services.vault.AttachmentQueryCriteria, net.corda.core.node.services.vault.AttachmentSort) + public abstract void refreshNetworkMapCache() @NotNull public abstract java.util.List registeredFlows() public abstract void setFlowsDrainingModeEnabled(boolean) + public abstract void shutdown() @RPCReturnsObservables @NotNull public abstract net.corda.core.messaging.FlowHandle startFlowDynamic(Class>, Object...) @@ -2627,6 +2946,7 @@ public interface net.corda.core.messaging.CordaRPCOps extends net.corda.core.mes public abstract net.corda.core.messaging.DataFeed, net.corda.core.messaging.StateMachineUpdate> stateMachinesFeed() @NotNull public abstract java.util.List stateMachinesSnapshot() + public abstract void terminate(boolean) @NotNull public abstract net.corda.core.crypto.SecureHash uploadAttachment(java.io.InputStream) @NotNull @@ -2676,9 +2996,11 @@ public final class net.corda.core.messaging.DataFeed extends java.lang.Object @NotNull public final rx.Observable getUpdates() public int hashCode() + @NotNull public String toString() ## @DoNotImplement +@CordaSerializable public interface net.corda.core.messaging.FlowHandle extends java.lang.AutoCloseable public abstract void close() @NotNull @@ -2703,9 +3025,11 @@ public final class net.corda.core.messaging.FlowHandleImpl extends java.lang.Obj @NotNull public net.corda.core.concurrent.CordaFuture getReturnValue() public int hashCode() + @NotNull public String toString() ## @DoNotImplement +@CordaSerializable public interface net.corda.core.messaging.FlowProgressHandle extends net.corda.core.messaging.FlowHandle public abstract void close() @NotNull @@ -2748,6 +3072,7 @@ public final class net.corda.core.messaging.FlowProgressHandleImpl extends java. @Nullable public net.corda.core.messaging.DataFeed getStepsTreeIndexFeed() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -2779,6 +3104,7 @@ public final class net.corda.core.messaging.ParametersUpdateInfo extends java.la @NotNull public final java.time.Instant getUpdateDeadline() public int hashCode() + @NotNull public String toString() ## @DoNotImplement @@ -2838,6 +3164,7 @@ public final class net.corda.core.messaging.StateMachineTransactionMapping exten @NotNull public final net.corda.core.crypto.SecureHash getTransactionId() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -2858,6 +3185,7 @@ public static final class net.corda.core.messaging.StateMachineUpdate$Added exte @NotNull public final net.corda.core.messaging.StateMachineInfo getStateMachineInfo() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -2875,6 +3203,7 @@ public static final class net.corda.core.messaging.StateMachineUpdate$Removed ex @NotNull public final net.corda.core.utilities.Try getResult() public int hashCode() + @NotNull public String toString() ## @DoNotImplement @@ -2885,8 +3214,27 @@ public interface net.corda.core.node.AppServiceHub extends net.corda.core.node.S public abstract net.corda.core.messaging.FlowProgressHandle startTrackedFlow(net.corda.core.flows.FlowLogic) ## @CordaSerializable +public final class net.corda.core.node.JavaPackageName extends java.lang.Object + public (String) + @NotNull + public final String component1() + @NotNull + public final net.corda.core.node.JavaPackageName copy(String) + public boolean equals(Object) + @NotNull + public final String getName() + public int hashCode() + public final boolean owns(String) + @NotNull + public String toString() +## +@CordaSerializable public final class net.corda.core.node.NetworkParameters extends java.lang.Object + @DeprecatedConstructorForDeserialization public (int, java.util.List, int, int, java.time.Instant, int, java.util.Map>) + @DeprecatedConstructorForDeserialization + public (int, java.util.List, int, int, java.time.Instant, int, java.util.Map>, java.time.Duration) + public (int, java.util.List, int, int, java.time.Instant, int, java.util.Map>, java.time.Duration, java.util.Map) public final int component1() @NotNull public final java.util.List component2() @@ -2898,9 +3246,19 @@ public final class net.corda.core.node.NetworkParameters extends java.lang.Objec @NotNull public final java.util.Map> component7() @NotNull + public final java.time.Duration component8() + @NotNull + public final java.util.Map component9() + @NotNull public final net.corda.core.node.NetworkParameters copy(int, java.util.List, int, int, java.time.Instant, int, java.util.Map>) + @NotNull + public final net.corda.core.node.NetworkParameters copy(int, java.util.List, int, int, java.time.Instant, int, java.util.Map>, java.time.Duration) + @NotNull + public final net.corda.core.node.NetworkParameters copy(int, java.util.List, int, int, java.time.Instant, int, java.util.Map>, java.time.Duration, java.util.Map) public boolean equals(Object) public final int getEpoch() + @NotNull + public final java.time.Duration getEventHorizon() public final int getMaxMessageSize() public final int getMaxTransactionSize() public final int getMinimumPlatformVersion() @@ -2908,11 +3266,18 @@ public final class net.corda.core.node.NetworkParameters extends java.lang.Objec public final java.time.Instant getModifiedTime() @NotNull public final java.util.List getNotaries() + @Nullable + public final java.security.PublicKey getOwnerOf(String) + @NotNull + public final java.util.Map getPackageOwnership() @NotNull public final java.util.Map> getWhitelistedContractImplementations() public int hashCode() + @NotNull public String toString() ## +public final class net.corda.core.node.NetworkParametersKt extends java.lang.Object +## @CordaSerializable public final class net.corda.core.node.NodeInfo extends java.lang.Object public (java.util.List, java.util.List, int, long) @@ -2939,6 +3304,7 @@ public final class net.corda.core.node.NodeInfo extends java.lang.Object @NotNull public final net.corda.core.identity.Party identityFromX500Name(net.corda.core.identity.CordaX500Name) public final boolean isLegalIdentity(net.corda.core.identity.Party) + @NotNull public String toString() ## @CordaSerializable @@ -2954,6 +3320,7 @@ public final class net.corda.core.node.NotaryInfo extends java.lang.Object public final net.corda.core.identity.Party getIdentity() public final boolean getValidating() public int hashCode() + @NotNull public String toString() ## @DoNotImplement @@ -2973,6 +3340,8 @@ public interface net.corda.core.node.ServiceHub extends net.corda.core.node.Serv @NotNull public abstract net.corda.core.crypto.TransactionSignature createSignature(net.corda.core.transactions.SignedTransaction, java.security.PublicKey) @NotNull + public abstract net.corda.core.cordapp.CordappContext getAppContext() + @NotNull public abstract java.time.Clock getClock() @NotNull public abstract net.corda.core.node.services.ContractUpgradeService getContractUpgradeService() @@ -3004,6 +3373,9 @@ public interface net.corda.core.node.ServiceHub extends net.corda.core.node.Serv public abstract net.corda.core.transactions.SignedTransaction signInitialTransaction(net.corda.core.transactions.TransactionBuilder, java.security.PublicKey) @NotNull public abstract net.corda.core.contracts.StateAndRef toStateAndRef(net.corda.core.contracts.StateRef) + public abstract void withEntityManager(java.util.function.Consumer) + @NotNull + public abstract T withEntityManager(kotlin.jvm.functions.Function1) ## @DoNotImplement public interface net.corda.core.node.ServicesForResolution @@ -3025,6 +3397,10 @@ public final class net.corda.core.node.StatesToRecord extends java.lang.Enum public static net.corda.core.node.StatesToRecord valueOf(String) public static net.corda.core.node.StatesToRecord[] values() ## +@CordaSerializable +public final class net.corda.core.node.ZoneVersionTooLowException extends net.corda.core.CordaRuntimeException + public (String) +## @DoNotImplement public interface net.corda.core.node.services.AttachmentStorage public abstract boolean hasAttachment(net.corda.core.crypto.SecureHash) @@ -3118,6 +3494,7 @@ public static final class net.corda.core.node.services.NetworkMapCache$MapChange @NotNull public net.corda.core.node.NodeInfo getNode() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -3135,6 +3512,7 @@ public static final class net.corda.core.node.services.NetworkMapCache$MapChange @NotNull public final net.corda.core.node.NodeInfo getPreviousNode() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -3148,6 +3526,7 @@ public static final class net.corda.core.node.services.NetworkMapCache$MapChange @NotNull public net.corda.core.node.NodeInfo getNode() public int hashCode() + @NotNull public String toString() ## @DoNotImplement @@ -3196,6 +3575,7 @@ public static final class net.corda.core.node.services.PartyInfo$DistributedNode @NotNull public net.corda.core.identity.Party getParty() public int hashCode() + @NotNull public String toString() ## public static final class net.corda.core.node.services.PartyInfo$SingleNode extends net.corda.core.node.services.PartyInfo @@ -3212,6 +3592,7 @@ public static final class net.corda.core.node.services.PartyInfo$SingleNode exte @NotNull public net.corda.core.identity.Party getParty() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -3239,6 +3620,8 @@ public interface net.corda.core.node.services.TransactionStorage public abstract rx.Observable getUpdates() @NotNull public abstract net.corda.core.messaging.DataFeed, net.corda.core.transactions.SignedTransaction> track() + @NotNull + public abstract net.corda.core.concurrent.CordaFuture trackTransaction(net.corda.core.crypto.SecureHash) ## @DoNotImplement public interface net.corda.core.node.services.TransactionVerifierService @@ -3263,6 +3646,35 @@ public static final class net.corda.core.node.services.Vault$Companion extends j public final net.corda.core.node.services.Vault$Update getNoUpdate() ## @CordaSerializable +public static final class net.corda.core.node.services.Vault$ConstraintInfo extends java.lang.Object + public (net.corda.core.contracts.AttachmentConstraint) + @NotNull + public final net.corda.core.contracts.AttachmentConstraint component1() + @NotNull + public final net.corda.core.node.services.Vault$ConstraintInfo copy(net.corda.core.contracts.AttachmentConstraint) + @Nullable + public final byte[] data() + public boolean equals(Object) + @NotNull + public final net.corda.core.contracts.AttachmentConstraint getConstraint() + public int hashCode() + @NotNull + public String toString() + @NotNull + public final net.corda.core.node.services.Vault$ConstraintInfo$Type type() + public static final net.corda.core.node.services.Vault$ConstraintInfo$Companion Companion +## +public static final class net.corda.core.node.services.Vault$ConstraintInfo$Companion extends java.lang.Object + @NotNull + public final net.corda.core.node.services.Vault$ConstraintInfo constraintInfo(net.corda.core.node.services.Vault$ConstraintInfo$Type, byte[]) +## +@CordaSerializable +public static final class net.corda.core.node.services.Vault$ConstraintInfo$Type extends java.lang.Enum + protected () + public static net.corda.core.node.services.Vault$ConstraintInfo$Type valueOf(String) + public static net.corda.core.node.services.Vault$ConstraintInfo$Type[] values() +## +@CordaSerializable public static final class net.corda.core.node.services.Vault$Page extends java.lang.Object public (java.util.List>, java.util.List, long, net.corda.core.node.services.Vault$StateStatus, java.util.List) @NotNull @@ -3287,13 +3699,24 @@ public static final class net.corda.core.node.services.Vault$Page extends java.l public final java.util.List getStatesMetadata() public final long getTotalStatesAvailable() public int hashCode() + @NotNull public String toString() ## @CordaSerializable +public static final class net.corda.core.node.services.Vault$RelevancyStatus extends java.lang.Enum + protected () + public static net.corda.core.node.services.Vault$RelevancyStatus valueOf(String) + public static net.corda.core.node.services.Vault$RelevancyStatus[] values() +## +@CordaSerializable public static final class net.corda.core.node.services.Vault$StateMetadata extends java.lang.Object public (net.corda.core.contracts.StateRef, String, java.time.Instant, java.time.Instant, net.corda.core.node.services.Vault$StateStatus, net.corda.core.identity.AbstractParty, String, java.time.Instant) + public (net.corda.core.contracts.StateRef, String, java.time.Instant, java.time.Instant, net.corda.core.node.services.Vault$StateStatus, net.corda.core.identity.AbstractParty, String, java.time.Instant, net.corda.core.node.services.Vault$RelevancyStatus) + public (net.corda.core.contracts.StateRef, String, java.time.Instant, java.time.Instant, net.corda.core.node.services.Vault$StateStatus, net.corda.core.identity.AbstractParty, String, java.time.Instant, net.corda.core.node.services.Vault$RelevancyStatus, net.corda.core.node.services.Vault$ConstraintInfo) @NotNull public final net.corda.core.contracts.StateRef component1() + @Nullable + public final net.corda.core.node.services.Vault$ConstraintInfo component10() @NotNull public final String component2() @NotNull @@ -3308,10 +3731,18 @@ public static final class net.corda.core.node.services.Vault$StateMetadata exten public final String component7() @Nullable public final java.time.Instant component8() + @Nullable + public final net.corda.core.node.services.Vault$RelevancyStatus component9() @NotNull public final net.corda.core.node.services.Vault$StateMetadata copy(net.corda.core.contracts.StateRef, String, java.time.Instant, java.time.Instant, net.corda.core.node.services.Vault$StateStatus, net.corda.core.identity.AbstractParty, String, java.time.Instant) + @NotNull + public final net.corda.core.node.services.Vault$StateMetadata copy(net.corda.core.contracts.StateRef, String, java.time.Instant, java.time.Instant, net.corda.core.node.services.Vault$StateStatus, net.corda.core.identity.AbstractParty, String, java.time.Instant, net.corda.core.node.services.Vault$RelevancyStatus) + @NotNull + public final net.corda.core.node.services.Vault$StateMetadata copy(net.corda.core.contracts.StateRef, String, java.time.Instant, java.time.Instant, net.corda.core.node.services.Vault$StateStatus, net.corda.core.identity.AbstractParty, String, java.time.Instant, net.corda.core.node.services.Vault$RelevancyStatus, net.corda.core.node.services.Vault$ConstraintInfo) public boolean equals(Object) @Nullable + public final net.corda.core.node.services.Vault$ConstraintInfo getConstraintInfo() + @Nullable public final java.time.Instant getConsumedTime() @NotNull public final String getContractStateClassName() @@ -3325,9 +3756,12 @@ public static final class net.corda.core.node.services.Vault$StateMetadata exten public final java.time.Instant getRecordedTime() @NotNull public final net.corda.core.contracts.StateRef getRef() + @Nullable + public final net.corda.core.node.services.Vault$RelevancyStatus getRelevancyStatus() @NotNull public final net.corda.core.node.services.Vault$StateStatus getStatus() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -3418,6 +3852,7 @@ public interface net.corda.core.node.services.VaultService public abstract net.corda.core.concurrent.CordaFuture> whenConsumed(net.corda.core.contracts.StateRef) ## public final class net.corda.core.node.services.VaultServiceKt extends java.lang.Object + public static final int MAX_CONSTRAINT_DATA_SIZE = 563 ## @CordaSerializable public final class net.corda.core.node.services.vault.AggregateFunctionType extends java.lang.Enum @@ -3464,6 +3899,7 @@ public static final class net.corda.core.node.services.vault.AttachmentQueryCrit @Nullable public final net.corda.core.node.services.vault.ColumnPredicate getUploaderCondition() public int hashCode() + @NotNull public String toString() @NotNull public java.util.Collection visit(net.corda.core.node.services.vault.AttachmentsQueryCriteriaParser) @@ -3489,6 +3925,7 @@ public final class net.corda.core.node.services.vault.AttachmentSort extends net @NotNull public final java.util.Collection getColumns() public int hashCode() + @NotNull public String toString() ## public static final class net.corda.core.node.services.vault.AttachmentSort$AttachmentSortAttribute extends java.lang.Enum @@ -3513,6 +3950,7 @@ public static final class net.corda.core.node.services.vault.AttachmentSort$Atta @NotNull public final net.corda.core.node.services.vault.AttachmentSort$AttachmentSortAttribute getSortAttribute() public int hashCode() + @NotNull public String toString() ## public interface net.corda.core.node.services.vault.AttachmentsQueryCriteriaParser extends net.corda.core.node.services.vault.BaseQueryCriteriaParser @@ -3555,50 +3993,88 @@ public final class net.corda.core.node.services.vault.Builder extends java.lang. @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression avg(kotlin.reflect.KProperty1, java.util.List>, net.corda.core.node.services.vault.Sort$Direction) @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression avg(net.corda.core.node.services.vault.FieldInfo) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression avg(net.corda.core.node.services.vault.FieldInfo, java.util.List) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression avg(net.corda.core.node.services.vault.FieldInfo, java.util.List, net.corda.core.node.services.vault.Sort$Direction) + @NotNull public final net.corda.core.node.services.vault.ColumnPredicate$Between between(R, R) @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression between(reflect.Field, R, R) @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression between(kotlin.reflect.KProperty1, R, R) @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression between(net.corda.core.node.services.vault.FieldInfo, R, R) + @NotNull public final net.corda.core.node.services.vault.ColumnPredicate$BinaryComparison compare(net.corda.core.node.services.vault.BinaryComparisonOperator, R) @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression comparePredicate(reflect.Field, net.corda.core.node.services.vault.BinaryComparisonOperator, R) @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression comparePredicate(kotlin.reflect.KProperty1, net.corda.core.node.services.vault.BinaryComparisonOperator, R) @NotNull + public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression comparePredicate(net.corda.core.node.services.vault.FieldInfo, net.corda.core.node.services.vault.BinaryComparisonOperator, R) + @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression count(reflect.Field) @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression count(kotlin.reflect.KProperty1) @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression count(net.corda.core.node.services.vault.FieldInfo) + @NotNull public final net.corda.core.node.services.vault.ColumnPredicate$EqualityComparison equal(R) @NotNull + public final net.corda.core.node.services.vault.ColumnPredicate$EqualityComparison equal(R, boolean) + @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression equal(reflect.Field, R) @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression equal(reflect.Field, R, boolean) + @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression equal(kotlin.reflect.KProperty1, R) @NotNull + public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression equal(kotlin.reflect.KProperty1, R, boolean) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression equal(net.corda.core.node.services.vault.FieldInfo, R) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression equal(net.corda.core.node.services.vault.FieldInfo, R, boolean) + @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression functionPredicate(reflect.Field, net.corda.core.node.services.vault.ColumnPredicate, java.util.List>, net.corda.core.node.services.vault.Sort$Direction) @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression functionPredicate(kotlin.reflect.KProperty1, net.corda.core.node.services.vault.ColumnPredicate, java.util.List>, net.corda.core.node.services.vault.Sort$Direction) @NotNull + public final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression functionPredicate(net.corda.core.node.services.vault.FieldInfo, net.corda.core.node.services.vault.ColumnPredicate, java.util.List>, net.corda.core.node.services.vault.Sort$Direction) + @NotNull public final net.corda.core.node.services.vault.ColumnPredicate$BinaryComparison greaterThan(R) @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression greaterThan(reflect.Field, R) @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression greaterThan(kotlin.reflect.KProperty1, R) @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression greaterThan(net.corda.core.node.services.vault.FieldInfo, R) + @NotNull public final net.corda.core.node.services.vault.ColumnPredicate$BinaryComparison greaterThanOrEqual(R) @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression greaterThanOrEqual(reflect.Field, R) @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression greaterThanOrEqual(kotlin.reflect.KProperty1, R) @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression greaterThanOrEqual(net.corda.core.node.services.vault.FieldInfo, R) + @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression in(reflect.Field, java.util.Collection) @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression in(reflect.Field, java.util.Collection, boolean) + @NotNull public final net.corda.core.node.services.vault.ColumnPredicate$CollectionExpression in(java.util.Collection) @NotNull + public final net.corda.core.node.services.vault.ColumnPredicate$CollectionExpression in(java.util.Collection, boolean) + @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression in(kotlin.reflect.KProperty1, java.util.Collection) @NotNull + public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression in(kotlin.reflect.KProperty1, java.util.Collection, boolean) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression in(net.corda.core.node.services.vault.FieldInfo, java.util.Collection) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression in(net.corda.core.node.services.vault.FieldInfo, java.util.Collection, boolean) + @NotNull public final net.corda.core.node.services.vault.ColumnPredicate$NullExpression isNotNull() @NotNull public final net.corda.core.node.services.vault.ColumnPredicate$NullExpression isNull() @@ -3607,24 +4083,40 @@ public final class net.corda.core.node.services.vault.Builder extends java.lang. @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression isNull(kotlin.reflect.KProperty1) @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression isNull(net.corda.core.node.services.vault.FieldInfo) + @NotNull public final net.corda.core.node.services.vault.ColumnPredicate$BinaryComparison lessThan(R) @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression lessThan(reflect.Field, R) @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression lessThan(kotlin.reflect.KProperty1, R) @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression lessThan(net.corda.core.node.services.vault.FieldInfo, R) + @NotNull public final net.corda.core.node.services.vault.ColumnPredicate$BinaryComparison lessThanOrEqual(R) @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression lessThanOrEqual(reflect.Field, R) @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression lessThanOrEqual(kotlin.reflect.KProperty1, R) @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression lessThanOrEqual(net.corda.core.node.services.vault.FieldInfo, R) + @NotNull public final net.corda.core.node.services.vault.ColumnPredicate$Likeness like(String) @NotNull + public final net.corda.core.node.services.vault.ColumnPredicate$Likeness like(String, boolean) + @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression like(reflect.Field, String) @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression like(reflect.Field, String, boolean) + @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression like(kotlin.reflect.KProperty1, String) @NotNull + public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression like(kotlin.reflect.KProperty1, String, boolean) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression like(net.corda.core.node.services.vault.FieldInfo, String) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression like(net.corda.core.node.services.vault.FieldInfo, String, boolean) + @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression max(reflect.Field) @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression max(reflect.Field, java.util.List) @@ -3633,6 +4125,12 @@ public final class net.corda.core.node.services.vault.Builder extends java.lang. @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression max(kotlin.reflect.KProperty1, java.util.List>, net.corda.core.node.services.vault.Sort$Direction) @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression max(net.corda.core.node.services.vault.FieldInfo) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression max(net.corda.core.node.services.vault.FieldInfo, java.util.List) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression max(net.corda.core.node.services.vault.FieldInfo, java.util.List, net.corda.core.node.services.vault.Sort$Direction) + @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression min(reflect.Field) @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression min(reflect.Field, java.util.List) @@ -3641,32 +4139,72 @@ public final class net.corda.core.node.services.vault.Builder extends java.lang. @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression min(kotlin.reflect.KProperty1, java.util.List>, net.corda.core.node.services.vault.Sort$Direction) @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression min(net.corda.core.node.services.vault.FieldInfo) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression min(net.corda.core.node.services.vault.FieldInfo, java.util.List) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression min(net.corda.core.node.services.vault.FieldInfo, java.util.List, net.corda.core.node.services.vault.Sort$Direction) + @NotNull public final net.corda.core.node.services.vault.ColumnPredicate$EqualityComparison notEqual(R) @NotNull + public final net.corda.core.node.services.vault.ColumnPredicate$EqualityComparison notEqual(R, boolean) + @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notEqual(reflect.Field, R) @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notEqual(reflect.Field, R, boolean) + @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notEqual(kotlin.reflect.KProperty1, R) @NotNull + public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notEqual(kotlin.reflect.KProperty1, R, boolean) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notEqual(net.corda.core.node.services.vault.FieldInfo, R) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notEqual(net.corda.core.node.services.vault.FieldInfo, R, boolean) + @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notIn(reflect.Field, java.util.Collection) @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notIn(reflect.Field, java.util.Collection, boolean) + @NotNull public final net.corda.core.node.services.vault.ColumnPredicate$CollectionExpression notIn(java.util.Collection) @NotNull + public final net.corda.core.node.services.vault.ColumnPredicate$CollectionExpression notIn(java.util.Collection, boolean) + @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notIn(kotlin.reflect.KProperty1, java.util.Collection) @NotNull + public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notIn(kotlin.reflect.KProperty1, java.util.Collection, boolean) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notIn(net.corda.core.node.services.vault.FieldInfo, java.util.Collection) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notIn(net.corda.core.node.services.vault.FieldInfo, java.util.Collection, boolean) + @NotNull public final net.corda.core.node.services.vault.ColumnPredicate$Likeness notLike(String) @NotNull + public final net.corda.core.node.services.vault.ColumnPredicate$Likeness notLike(String, boolean) + @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notLike(reflect.Field, String) @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notLike(reflect.Field, String, boolean) + @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notLike(kotlin.reflect.KProperty1, String) @NotNull + public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notLike(kotlin.reflect.KProperty1, String, boolean) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notLike(net.corda.core.node.services.vault.FieldInfo, String) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notLike(net.corda.core.node.services.vault.FieldInfo, String, boolean) + @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notNull(reflect.Field) @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notNull(kotlin.reflect.KProperty1) @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression notNull(net.corda.core.node.services.vault.FieldInfo) + @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression predicate(reflect.Field, net.corda.core.node.services.vault.ColumnPredicate) @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression predicate(kotlin.reflect.KProperty1, net.corda.core.node.services.vault.ColumnPredicate) @NotNull + public final net.corda.core.node.services.vault.CriteriaExpression$ColumnPredicateExpression predicate(net.corda.core.node.services.vault.FieldInfo, net.corda.core.node.services.vault.ColumnPredicate) + @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression sum(reflect.Field) @NotNull public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression sum(reflect.Field, java.util.List) @@ -3674,6 +4212,12 @@ public final class net.corda.core.node.services.vault.Builder extends java.lang. public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression sum(reflect.Field, java.util.List, net.corda.core.node.services.vault.Sort$Direction) @NotNull public final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression sum(kotlin.reflect.KProperty1, java.util.List>, net.corda.core.node.services.vault.Sort$Direction) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression sum(net.corda.core.node.services.vault.FieldInfo) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression sum(net.corda.core.node.services.vault.FieldInfo, java.util.List) + @NotNull + public static final net.corda.core.node.services.vault.CriteriaExpression$AggregateFunctionExpression sum(net.corda.core.node.services.vault.FieldInfo, java.util.List, net.corda.core.node.services.vault.Sort$Direction) public static final net.corda.core.node.services.vault.Builder INSTANCE ## @DoNotImplement @@ -3688,10 +4232,12 @@ public final class net.corda.core.node.services.vault.Column extends java.lang.O public (String, Class) public (reflect.Field) public (kotlin.reflect.KProperty1) + public (net.corda.core.node.services.vault.FieldInfo) @NotNull public final Class getDeclaringClass() @NotNull public final String getName() + public static final net.corda.core.node.services.vault.Column$Companion Companion ## @CordaSerializable public abstract class net.corda.core.node.services.vault.ColumnPredicate extends java.lang.Object @@ -3707,6 +4253,7 @@ public static final class net.corda.core.node.services.vault.ColumnPredicate$Agg @NotNull public final net.corda.core.node.services.vault.AggregateFunctionType getType() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -3724,6 +4271,7 @@ public static final class net.corda.core.node.services.vault.ColumnPredicate$Bet @NotNull public final C getRightToLiteral() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -3741,6 +4289,7 @@ public static final class net.corda.core.node.services.vault.ColumnPredicate$Bin @NotNull public final C getRightLiteral() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -3758,6 +4307,7 @@ public static final class net.corda.core.node.services.vault.ColumnPredicate$Col @NotNull public final java.util.Collection getRightLiteral() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -3773,6 +4323,7 @@ public static final class net.corda.core.node.services.vault.ColumnPredicate$Equ public final net.corda.core.node.services.vault.EqualityComparisonOperator getOperator() public final C getRightLiteral() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -3790,6 +4341,7 @@ public static final class net.corda.core.node.services.vault.ColumnPredicate$Lik @NotNull public final String getRightLiteral() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -3803,6 +4355,7 @@ public static final class net.corda.core.node.services.vault.ColumnPredicate$Nul @NotNull public final net.corda.core.node.services.vault.NullOperator getOperator() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -3831,6 +4384,7 @@ public static final class net.corda.core.node.services.vault.CriteriaExpression$ @NotNull public final net.corda.core.node.services.vault.ColumnPredicate getPredicate() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -3852,6 +4406,7 @@ public static final class net.corda.core.node.services.vault.CriteriaExpression$ @NotNull public final net.corda.core.node.services.vault.CriteriaExpression getRight() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -3869,6 +4424,7 @@ public static final class net.corda.core.node.services.vault.CriteriaExpression$ @NotNull public final net.corda.core.node.services.vault.ColumnPredicate getPredicate() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -3882,6 +4438,7 @@ public static final class net.corda.core.node.services.vault.CriteriaExpression$ @NotNull public final net.corda.core.node.services.vault.CriteriaExpression getExpression() public int hashCode() + @NotNull public String toString() ## @DoNotImplement @@ -3891,6 +4448,13 @@ public final class net.corda.core.node.services.vault.EqualityComparisonOperator public static net.corda.core.node.services.vault.EqualityComparisonOperator valueOf(String) public static net.corda.core.node.services.vault.EqualityComparisonOperator[] values() ## +public final class net.corda.core.node.services.vault.FieldInfo extends java.lang.Object + public (String, Class) + @NotNull + public final Class getEntityClass() + @NotNull + public final String getName() +## public interface net.corda.core.node.services.vault.GenericQueryCriteria @NotNull public abstract java.util.Collection visit(P) @@ -3961,6 +4525,7 @@ public final class net.corda.core.node.services.vault.PageSpecification extends public final int getPageSize() public int hashCode() public final boolean isDefault() + @NotNull public String toString() ## @CordaSerializable @@ -3983,9 +4548,15 @@ public static final class net.corda.core.node.services.vault.QueryCriteria$AndCo @CordaSerializable public abstract static class net.corda.core.node.services.vault.QueryCriteria$CommonQueryCriteria extends net.corda.core.node.services.vault.QueryCriteria public () + @NotNull + public java.util.Set getConstraintTypes() + @NotNull + public java.util.Set getConstraints() @Nullable public abstract java.util.Set> getContractStateTypes() @NotNull + public net.corda.core.node.services.Vault$RelevancyStatus getRelevancyStatus() + @NotNull public abstract net.corda.core.node.services.Vault$StateStatus getStatus() @NotNull public java.util.Collection visit(net.corda.core.node.services.vault.IQueryCriteriaParser) @@ -4000,6 +4571,7 @@ public static final class net.corda.core.node.services.vault.QueryCriteria$Fungi public (java.util.List, java.util.List, net.corda.core.node.services.vault.ColumnPredicate, java.util.List, java.util.List) public (java.util.List, java.util.List, net.corda.core.node.services.vault.ColumnPredicate, java.util.List, java.util.List, net.corda.core.node.services.Vault$StateStatus) public (java.util.List, java.util.List, net.corda.core.node.services.vault.ColumnPredicate, java.util.List, java.util.List, net.corda.core.node.services.Vault$StateStatus, java.util.Set>) + public (java.util.List, java.util.List, net.corda.core.node.services.vault.ColumnPredicate, java.util.List, java.util.List, net.corda.core.node.services.Vault$StateStatus, java.util.Set>, net.corda.core.node.services.Vault$RelevancyStatus) @Nullable public final java.util.List component1() @Nullable @@ -4015,7 +4587,11 @@ public static final class net.corda.core.node.services.vault.QueryCriteria$Fungi @Nullable public final java.util.Set> component7() @NotNull + public final net.corda.core.node.services.Vault$RelevancyStatus component8() + @NotNull public final net.corda.core.node.services.vault.QueryCriteria$FungibleAssetQueryCriteria copy(java.util.List, java.util.List, net.corda.core.node.services.vault.ColumnPredicate, java.util.List, java.util.List, net.corda.core.node.services.Vault$StateStatus, java.util.Set>) + @NotNull + public final net.corda.core.node.services.vault.QueryCriteria$FungibleAssetQueryCriteria copy(java.util.List, java.util.List, net.corda.core.node.services.vault.ColumnPredicate, java.util.List, java.util.List, net.corda.core.node.services.Vault$StateStatus, java.util.Set>, net.corda.core.node.services.Vault$RelevancyStatus) public boolean equals(Object) @Nullable public java.util.Set> getContractStateTypes() @@ -4030,8 +4606,44 @@ public static final class net.corda.core.node.services.vault.QueryCriteria$Fungi @Nullable public final net.corda.core.node.services.vault.ColumnPredicate getQuantity() @NotNull + public net.corda.core.node.services.Vault$RelevancyStatus getRelevancyStatus() + @NotNull public net.corda.core.node.services.Vault$StateStatus getStatus() public int hashCode() + @NotNull + public String toString() + @NotNull + public java.util.Collection visit(net.corda.core.node.services.vault.IQueryCriteriaParser) +## +@CordaSerializable +public static final class net.corda.core.node.services.vault.QueryCriteria$FungibleStateQueryCriteria extends net.corda.core.node.services.vault.QueryCriteria$CommonQueryCriteria + public () + public (java.util.List, net.corda.core.node.services.vault.ColumnPredicate, net.corda.core.node.services.Vault$StateStatus, java.util.Set>, net.corda.core.node.services.Vault$RelevancyStatus) + @Nullable + public final java.util.List component1() + @Nullable + public final net.corda.core.node.services.vault.ColumnPredicate component2() + @NotNull + public final net.corda.core.node.services.Vault$StateStatus component3() + @Nullable + public final java.util.Set> component4() + @NotNull + public final net.corda.core.node.services.Vault$RelevancyStatus component5() + @NotNull + public final net.corda.core.node.services.vault.QueryCriteria$FungibleStateQueryCriteria copy(java.util.List, net.corda.core.node.services.vault.ColumnPredicate, net.corda.core.node.services.Vault$StateStatus, java.util.Set>, net.corda.core.node.services.Vault$RelevancyStatus) + public boolean equals(Object) + @Nullable + public java.util.Set> getContractStateTypes() + @Nullable + public final java.util.List getParticipants() + @Nullable + public final net.corda.core.node.services.vault.ColumnPredicate getQuantity() + @NotNull + public net.corda.core.node.services.Vault$RelevancyStatus getRelevancyStatus() + @NotNull + public net.corda.core.node.services.Vault$StateStatus getStatus() + public int hashCode() + @NotNull public String toString() @NotNull public java.util.Collection visit(net.corda.core.node.services.vault.IQueryCriteriaParser) @@ -4044,7 +4656,9 @@ public static final class net.corda.core.node.services.vault.QueryCriteria$Linea public (java.util.List, java.util.List, java.util.List) public (java.util.List, java.util.List, java.util.List, net.corda.core.node.services.Vault$StateStatus) public (java.util.List, java.util.List, java.util.List, net.corda.core.node.services.Vault$StateStatus, java.util.Set>) + public (java.util.List, java.util.List, java.util.List, net.corda.core.node.services.Vault$StateStatus, java.util.Set>, net.corda.core.node.services.Vault$RelevancyStatus) public (java.util.List, java.util.List, net.corda.core.node.services.Vault$StateStatus, java.util.Set>) + public (java.util.List, java.util.List, net.corda.core.node.services.Vault$StateStatus, java.util.Set>, net.corda.core.node.services.Vault$RelevancyStatus) @Nullable public final java.util.List component1() @Nullable @@ -4056,7 +4670,11 @@ public static final class net.corda.core.node.services.vault.QueryCriteria$Linea @Nullable public final java.util.Set> component5() @NotNull + public final net.corda.core.node.services.Vault$RelevancyStatus component6() + @NotNull public final net.corda.core.node.services.vault.QueryCriteria$LinearStateQueryCriteria copy(java.util.List, java.util.List, java.util.List, net.corda.core.node.services.Vault$StateStatus, java.util.Set>) + @NotNull + public final net.corda.core.node.services.vault.QueryCriteria$LinearStateQueryCriteria copy(java.util.List, java.util.List, java.util.List, net.corda.core.node.services.Vault$StateStatus, java.util.Set>, net.corda.core.node.services.Vault$RelevancyStatus) public boolean equals(Object) @Nullable public java.util.Set> getContractStateTypes() @@ -4065,10 +4683,13 @@ public static final class net.corda.core.node.services.vault.QueryCriteria$Linea @Nullable public final java.util.List getParticipants() @NotNull + public net.corda.core.node.services.Vault$RelevancyStatus getRelevancyStatus() + @NotNull public net.corda.core.node.services.Vault$StateStatus getStatus() @Nullable public final java.util.List getUuid() public int hashCode() + @NotNull public String toString() @NotNull public java.util.Collection visit(net.corda.core.node.services.vault.IQueryCriteriaParser) @@ -4098,6 +4719,7 @@ public static final class net.corda.core.node.services.vault.QueryCriteria$SoftL @NotNull public final net.corda.core.node.services.vault.QueryCriteria$SoftLockingType getType() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -4121,6 +4743,7 @@ public static final class net.corda.core.node.services.vault.QueryCriteria$TimeC @NotNull public final net.corda.core.node.services.vault.QueryCriteria$TimeInstantType getType() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -4134,6 +4757,7 @@ public static final class net.corda.core.node.services.vault.QueryCriteria$Vault public (net.corda.core.node.services.vault.CriteriaExpression) public (net.corda.core.node.services.vault.CriteriaExpression, net.corda.core.node.services.Vault$StateStatus) public (net.corda.core.node.services.vault.CriteriaExpression, net.corda.core.node.services.Vault$StateStatus, java.util.Set>) + public (net.corda.core.node.services.vault.CriteriaExpression, net.corda.core.node.services.Vault$StateStatus, java.util.Set>, net.corda.core.node.services.Vault$RelevancyStatus) @NotNull public final net.corda.core.node.services.vault.CriteriaExpression component1() @NotNull @@ -4141,15 +4765,22 @@ public static final class net.corda.core.node.services.vault.QueryCriteria$Vault @Nullable public final java.util.Set> component3() @NotNull + public final net.corda.core.node.services.Vault$RelevancyStatus component4() + @NotNull public final net.corda.core.node.services.vault.QueryCriteria$VaultCustomQueryCriteria copy(net.corda.core.node.services.vault.CriteriaExpression, net.corda.core.node.services.Vault$StateStatus, java.util.Set>) + @NotNull + public final net.corda.core.node.services.vault.QueryCriteria$VaultCustomQueryCriteria copy(net.corda.core.node.services.vault.CriteriaExpression, net.corda.core.node.services.Vault$StateStatus, java.util.Set>, net.corda.core.node.services.Vault$RelevancyStatus) public boolean equals(Object) @Nullable public java.util.Set> getContractStateTypes() @NotNull public final net.corda.core.node.services.vault.CriteriaExpression getExpression() @NotNull + public net.corda.core.node.services.Vault$RelevancyStatus getRelevancyStatus() + @NotNull public net.corda.core.node.services.Vault$StateStatus getStatus() public int hashCode() + @NotNull public String toString() @NotNull public java.util.Collection visit(net.corda.core.node.services.vault.IQueryCriteriaParser) @@ -4163,6 +4794,9 @@ public static final class net.corda.core.node.services.vault.QueryCriteria$Vault public (net.corda.core.node.services.Vault$StateStatus, java.util.Set>, java.util.List, java.util.List) public (net.corda.core.node.services.Vault$StateStatus, java.util.Set>, java.util.List, java.util.List, net.corda.core.node.services.vault.QueryCriteria$SoftLockingCondition) public (net.corda.core.node.services.Vault$StateStatus, java.util.Set>, java.util.List, java.util.List, net.corda.core.node.services.vault.QueryCriteria$SoftLockingCondition, net.corda.core.node.services.vault.QueryCriteria$TimeCondition) + public (net.corda.core.node.services.Vault$StateStatus, java.util.Set>, java.util.List, java.util.List, net.corda.core.node.services.vault.QueryCriteria$SoftLockingCondition, net.corda.core.node.services.vault.QueryCriteria$TimeCondition, net.corda.core.node.services.Vault$RelevancyStatus) + public (net.corda.core.node.services.Vault$StateStatus, java.util.Set>, java.util.List, java.util.List, net.corda.core.node.services.vault.QueryCriteria$SoftLockingCondition, net.corda.core.node.services.vault.QueryCriteria$TimeCondition, net.corda.core.node.services.Vault$RelevancyStatus, java.util.Set) + public (net.corda.core.node.services.Vault$StateStatus, java.util.Set>, java.util.List, java.util.List, net.corda.core.node.services.vault.QueryCriteria$SoftLockingCondition, net.corda.core.node.services.vault.QueryCriteria$TimeCondition, net.corda.core.node.services.Vault$RelevancyStatus, java.util.Set, java.util.Set) @NotNull public final net.corda.core.node.services.Vault$StateStatus component1() @Nullable @@ -4176,12 +4810,26 @@ public static final class net.corda.core.node.services.vault.QueryCriteria$Vault @Nullable public final net.corda.core.node.services.vault.QueryCriteria$TimeCondition component6() @NotNull + public final net.corda.core.node.services.Vault$RelevancyStatus component7() + @NotNull + public final java.util.Set component8() + @NotNull + public final java.util.Set component9() + @NotNull public final net.corda.core.node.services.vault.QueryCriteria$VaultQueryCriteria copy(net.corda.core.node.services.Vault$StateStatus, java.util.Set>, java.util.List, java.util.List, net.corda.core.node.services.vault.QueryCriteria$SoftLockingCondition, net.corda.core.node.services.vault.QueryCriteria$TimeCondition) + @NotNull + public final net.corda.core.node.services.vault.QueryCriteria$VaultQueryCriteria copy(net.corda.core.node.services.Vault$StateStatus, java.util.Set>, java.util.List, java.util.List, net.corda.core.node.services.vault.QueryCriteria$SoftLockingCondition, net.corda.core.node.services.vault.QueryCriteria$TimeCondition, net.corda.core.node.services.Vault$RelevancyStatus, java.util.Set, java.util.Set) public boolean equals(Object) + @NotNull + public java.util.Set getConstraintTypes() + @NotNull + public java.util.Set getConstraints() @Nullable public java.util.Set> getContractStateTypes() @Nullable public final java.util.List getNotary() + @NotNull + public net.corda.core.node.services.Vault$RelevancyStatus getRelevancyStatus() @Nullable public final net.corda.core.node.services.vault.QueryCriteria$SoftLockingCondition getSoftLockingCondition() @Nullable @@ -4191,6 +4839,7 @@ public static final class net.corda.core.node.services.vault.QueryCriteria$Vault @Nullable public final net.corda.core.node.services.vault.QueryCriteria$TimeCondition getTimeCondition() public int hashCode() + @NotNull public String toString() @NotNull public java.util.Collection visit(net.corda.core.node.services.vault.IQueryCriteriaParser) @@ -4200,6 +4849,8 @@ public final class net.corda.core.node.services.vault.QueryCriteriaUtils extends @NotNull public static final String getColumnName(net.corda.core.node.services.vault.Column) @NotNull + public static final net.corda.core.node.services.vault.FieldInfo getField(String, Class) + @NotNull public static final Class resolveEnclosingObjectFromColumn(net.corda.core.node.services.vault.Column) @NotNull public static final Class resolveEnclosingObjectFromExpression(net.corda.core.node.services.vault.CriteriaExpression) @@ -4218,6 +4869,7 @@ public final class net.corda.core.node.services.vault.Sort extends net.corda.cor @NotNull public final java.util.Collection getColumns() public int hashCode() + @NotNull public String toString() ## @DoNotImplement @@ -4274,6 +4926,7 @@ public static final class net.corda.core.node.services.vault.Sort$SortColumn ext @NotNull public final net.corda.core.node.services.vault.SortAttribute getSortAttribute() public int hashCode() + @NotNull public String toString() ## @DoNotImplement @@ -4303,6 +4956,7 @@ public static final class net.corda.core.node.services.vault.SortAttribute$Custo @NotNull public final String getEntityStateColumnName() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -4316,12 +4970,15 @@ public static final class net.corda.core.node.services.vault.SortAttribute$Stand @NotNull public final net.corda.core.node.services.vault.Sort$Attribute getAttribute() public int hashCode() + @NotNull public String toString() ## public final class net.corda.core.schemas.CommonSchema extends java.lang.Object public static final net.corda.core.schemas.CommonSchema INSTANCE ## public final class net.corda.core.schemas.CommonSchemaV1 extends net.corda.core.schemas.MappedSchema + @NotNull + public String getMigrationResource() public static final net.corda.core.schemas.CommonSchemaV1 INSTANCE ## @MappedSuperclass @@ -4362,14 +5019,34 @@ public static class net.corda.core.schemas.CommonSchemaV1$LinearState extends ne ## public class net.corda.core.schemas.MappedSchema extends java.lang.Object public (Class, int, Iterable>) + public boolean equals(Object) @NotNull public final Iterable> getMappedTypes() + @Nullable + public String getMigrationResource() @NotNull public final String getName() public final int getVersion() + public int hashCode() @NotNull public String toString() ## +public final class net.corda.core.schemas.MappedSchemaValidator extends java.lang.Object + @NotNull + public final java.util.List crossReferencesToOtherMappedSchema(net.corda.core.schemas.MappedSchema) + @NotNull + public final java.util.List fieldsFromOtherMappedSchema(net.corda.core.schemas.MappedSchema) + @NotNull + public final java.util.List methodsFromOtherMappedSchema(net.corda.core.schemas.MappedSchema) + public static final net.corda.core.schemas.MappedSchemaValidator INSTANCE +## +public static final class net.corda.core.schemas.MappedSchemaValidator$SchemaCrossReferenceReport extends java.lang.Object + public (String, String, String, String, String) + @NotNull + public String toString() + @NotNull + public final String toWarning() +## @MappedSuperclass @CordaSerializable public class net.corda.core.schemas.PersistentState extends java.lang.Object implements net.corda.core.schemas.StatePersistable @@ -4380,6 +5057,7 @@ public class net.corda.core.schemas.PersistentState extends java.lang.Object imp public void setStateRef(net.corda.core.schemas.PersistentStateRef) ## @Embeddable +@Immutable public class net.corda.core.schemas.PersistentStateRef extends java.lang.Object implements java.io.Serializable public () public (String, int) @@ -4396,6 +5074,7 @@ public class net.corda.core.schemas.PersistentStateRef extends java.lang.Object public int hashCode() public void setIndex(int) public void setTxId(String) + @NotNull public String toString() ## @CordaSerializable @@ -4412,6 +5091,11 @@ public interface net.corda.core.serialization.ClassWhitelist ## public @interface net.corda.core.serialization.ConstructorForDeserialization ## +public final class net.corda.core.serialization.ContextPropertyKeys extends java.lang.Enum + protected () + public static net.corda.core.serialization.ContextPropertyKeys valueOf(String) + public static net.corda.core.serialization.ContextPropertyKeys[] values() +## public @interface net.corda.core.serialization.CordaSerializable ## public @interface net.corda.core.serialization.CordaSerializationTransformEnumDefault @@ -4431,6 +5115,10 @@ public @interface net.corda.core.serialization.CordaSerializationTransformRename public @interface net.corda.core.serialization.DeprecatedConstructorForDeserialization public abstract int version() ## +@DoNotImplement +public interface net.corda.core.serialization.EncodingWhitelist + public abstract boolean acceptEncoding(net.corda.core.serialization.SerializationEncoding) +## @CordaSerializable public final class net.corda.core.serialization.MissingAttachmentsException extends net.corda.core.CordaException public (java.util.List) @@ -4451,15 +5139,24 @@ public final class net.corda.core.serialization.ObjectWithCompatibleContext exte @NotNull public final T getObj() public int hashCode() + @NotNull public String toString() ## +public @interface net.corda.core.serialization.SerializableCalculatedProperty +## public final class net.corda.core.serialization.SerializationAPIKt extends java.lang.Object @NotNull public static final net.corda.core.serialization.SerializedBytes serialize(T, net.corda.core.serialization.SerializationFactory, net.corda.core.serialization.SerializationContext) ## +@DoNotImplement public interface net.corda.core.serialization.SerializationContext @NotNull public abstract ClassLoader getDeserializationClassLoader() + @Nullable + public abstract net.corda.core.serialization.SerializationEncoding getEncoding() + @NotNull + public abstract net.corda.core.serialization.EncodingWhitelist getEncodingWhitelist() + public abstract boolean getLenientCarpenterEnabled() public abstract boolean getObjectReferencesEnabled() @NotNull public abstract net.corda.core.utilities.ByteSequence getPreferredSerializationVersion() @@ -4474,6 +5171,12 @@ public interface net.corda.core.serialization.SerializationContext @NotNull public abstract net.corda.core.serialization.SerializationContext withClassLoader(ClassLoader) @NotNull + public abstract net.corda.core.serialization.SerializationContext withEncoding(net.corda.core.serialization.SerializationEncoding) + @NotNull + public abstract net.corda.core.serialization.SerializationContext withEncodingWhitelist(net.corda.core.serialization.EncodingWhitelist) + @NotNull + public abstract net.corda.core.serialization.SerializationContext withLenientCarpenter() + @NotNull public abstract net.corda.core.serialization.SerializationContext withPreferredSerializationVersion(net.corda.core.utilities.ByteSequence) @NotNull public abstract net.corda.core.serialization.SerializationContext withProperty(Object, Object) @@ -4504,6 +5207,9 @@ public final class net.corda.core.serialization.SerializationDefaults extends ja public final net.corda.core.serialization.SerializationContext getSTORAGE_CONTEXT() public static final net.corda.core.serialization.SerializationDefaults INSTANCE ## +@DoNotImplement +public interface net.corda.core.serialization.SerializationEncoding +## public abstract class net.corda.core.serialization.SerializationFactory extends java.lang.Object public () public final T asCurrent(kotlin.jvm.functions.Function1) @@ -4551,6 +5257,9 @@ public final class net.corda.core.serialization.SerializedBytes extends net.cord public (byte[]) @NotNull public final net.corda.core.crypto.SecureHash getHash() + public static final net.corda.core.serialization.SerializedBytes$Companion Companion +## +public static final class net.corda.core.serialization.SerializedBytes$Companion extends java.lang.Object ## public final class net.corda.core.serialization.SingletonSerializationToken extends java.lang.Object implements net.corda.core.serialization.SerializationToken @NotNull @@ -4592,6 +5301,8 @@ public abstract class net.corda.core.transactions.BaseTransaction extends java.l @NotNull public abstract java.util.List> getOutputs() @NotNull + public abstract java.util.List getReferences() + @NotNull public final net.corda.core.contracts.StateAndRef outRef(int) @NotNull public final net.corda.core.contracts.StateAndRef outRef(net.corda.core.contracts.ContractState) @@ -4639,8 +5350,11 @@ public final class net.corda.core.transactions.ContractUpgradeFilteredTransactio @NotNull public java.util.List> getOutputs() @NotNull + public java.util.List getReferences() + @NotNull public final java.util.Map getVisibleComponents() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -4688,6 +5402,8 @@ public final class net.corda.core.transactions.ContractUpgradeLedgerTransaction @NotNull public final net.corda.core.contracts.PrivacySalt getPrivacySalt() @NotNull + public java.util.List> getReferences() + @NotNull public java.util.Set getRequiredSigningKeys() @NotNull public java.util.List getSigs() @@ -4696,6 +5412,7 @@ public final class net.corda.core.transactions.ContractUpgradeLedgerTransaction @NotNull public final String getUpgradedContractClassName() public int hashCode() + @NotNull public String toString() ## @DoNotImplement @@ -4724,6 +5441,8 @@ public final class net.corda.core.transactions.ContractUpgradeWireTransaction ex @NotNull public final net.corda.core.contracts.PrivacySalt getPrivacySalt() @NotNull + public java.util.List getReferences() + @NotNull public final java.util.List getSerializedComponents() @NotNull public final net.corda.core.crypto.SecureHash getUpgradedContractAttachmentId() @@ -4732,6 +5451,7 @@ public final class net.corda.core.transactions.ContractUpgradeWireTransaction ex public int hashCode() @NotNull public final net.corda.core.transactions.ContractUpgradeLedgerTransaction resolve(net.corda.core.node.ServicesForResolution, java.util.List) + @NotNull public String toString() ## public static final class net.corda.core.transactions.ContractUpgradeWireTransaction$Component extends java.lang.Enum @@ -4745,6 +5465,8 @@ public abstract class net.corda.core.transactions.CoreTransaction extends net.co public () @NotNull public abstract java.util.List getInputs() + @NotNull + public abstract java.util.List getReferences() ## @CordaSerializable public final class net.corda.core.transactions.FilteredComponentGroup extends net.corda.core.transactions.ComponentGroup @@ -4767,6 +5489,7 @@ public final class net.corda.core.transactions.FilteredComponentGroup extends ne @NotNull public final net.corda.core.crypto.PartialMerkleTree getPartialMerkleTree() public int hashCode() + @NotNull public String toString() ## @DoNotImplement @@ -4805,17 +5528,22 @@ public abstract class net.corda.core.transactions.FullTransaction extends net.co protected void checkBaseInvariants() @NotNull public abstract java.util.List> getInputs() + @NotNull + public abstract java.util.List> getReferences() ## @DoNotImplement @CordaSerializable public final class net.corda.core.transactions.LedgerTransaction extends net.corda.core.transactions.FullTransaction public (java.util.List>, java.util.List>, java.util.List>, java.util.List, net.corda.core.crypto.SecureHash, net.corda.core.identity.Party, net.corda.core.contracts.TimeWindow, net.corda.core.contracts.PrivacySalt) public (java.util.List>, java.util.List>, java.util.List>, java.util.List, net.corda.core.crypto.SecureHash, net.corda.core.identity.Party, net.corda.core.contracts.TimeWindow, net.corda.core.contracts.PrivacySalt, net.corda.core.node.NetworkParameters) + public (java.util.List>, java.util.List>, java.util.List>, java.util.List, net.corda.core.crypto.SecureHash, net.corda.core.identity.Party, net.corda.core.contracts.TimeWindow, net.corda.core.contracts.PrivacySalt, net.corda.core.node.NetworkParameters, java.util.List>) @NotNull public final java.util.List> commandsOfType(Class) @NotNull public final java.util.List> component1() @NotNull + public final java.util.List> component10() + @NotNull public final java.util.List> component2() @NotNull public final java.util.List> component3() @@ -4830,9 +5558,27 @@ public final class net.corda.core.transactions.LedgerTransaction extends net.cor @NotNull public final net.corda.core.contracts.PrivacySalt component8() @NotNull + public final net.corda.core.transactions.LedgerTransaction copy() + @NotNull + public final net.corda.core.transactions.LedgerTransaction copy(java.util.List>) + @NotNull + public final net.corda.core.transactions.LedgerTransaction copy(java.util.List>, java.util.List>) + @NotNull + public final net.corda.core.transactions.LedgerTransaction copy(java.util.List>, java.util.List>, java.util.List>) + @NotNull + public final net.corda.core.transactions.LedgerTransaction copy(java.util.List>, java.util.List>, java.util.List>, java.util.List) + @NotNull + public final net.corda.core.transactions.LedgerTransaction copy(java.util.List>, java.util.List>, java.util.List>, java.util.List, net.corda.core.crypto.SecureHash) + @NotNull + public final net.corda.core.transactions.LedgerTransaction copy(java.util.List>, java.util.List>, java.util.List>, java.util.List, net.corda.core.crypto.SecureHash, net.corda.core.identity.Party) + @NotNull + public final net.corda.core.transactions.LedgerTransaction copy(java.util.List>, java.util.List>, java.util.List>, java.util.List, net.corda.core.crypto.SecureHash, net.corda.core.identity.Party, net.corda.core.contracts.TimeWindow) + @NotNull public final net.corda.core.transactions.LedgerTransaction copy(java.util.List>, java.util.List>, java.util.List>, java.util.List, net.corda.core.crypto.SecureHash, net.corda.core.identity.Party, net.corda.core.contracts.TimeWindow, net.corda.core.contracts.PrivacySalt) @NotNull public final net.corda.core.transactions.LedgerTransaction copy(java.util.List>, java.util.List>, java.util.List>, java.util.List, net.corda.core.crypto.SecureHash, net.corda.core.identity.Party, net.corda.core.contracts.TimeWindow, net.corda.core.contracts.PrivacySalt, net.corda.core.node.NetworkParameters) + @NotNull + public final net.corda.core.transactions.LedgerTransaction copy(java.util.List>, java.util.List>, java.util.List>, java.util.List, net.corda.core.crypto.SecureHash, net.corda.core.identity.Party, net.corda.core.contracts.TimeWindow, net.corda.core.contracts.PrivacySalt, net.corda.core.node.NetworkParameters, java.util.List>) public boolean equals(Object) @NotNull public final java.util.List> filterCommands(Class, java.util.function.Predicate) @@ -4841,12 +5587,20 @@ public final class net.corda.core.transactions.LedgerTransaction extends net.cor @NotNull public final java.util.List filterInputs(Class, java.util.function.Predicate) @NotNull + public final java.util.List> filterReferenceInputRefs(Class, java.util.function.Predicate) + @NotNull + public final java.util.List filterReferenceInputs(Class, java.util.function.Predicate) + @NotNull public final net.corda.core.contracts.Command findCommand(Class, java.util.function.Predicate) @NotNull public final net.corda.core.contracts.StateAndRef findInRef(Class, java.util.function.Predicate) @NotNull public final T findInput(Class, java.util.function.Predicate) @NotNull + public final T findReference(Class, java.util.function.Predicate) + @NotNull + public final net.corda.core.contracts.StateAndRef findReferenceInputRef(Class, java.util.function.Predicate) + @NotNull public final net.corda.core.contracts.Attachment getAttachment(int) @NotNull public final net.corda.core.contracts.Attachment getAttachment(net.corda.core.crypto.SecureHash) @@ -4870,6 +5624,12 @@ public final class net.corda.core.transactions.LedgerTransaction extends net.cor public java.util.List> getOutputs() @NotNull public final net.corda.core.contracts.PrivacySalt getPrivacySalt() + @NotNull + public final net.corda.core.contracts.ContractState getReferenceInput(int) + @NotNull + public final java.util.List getReferenceStates() + @NotNull + public java.util.List> getReferences() @Nullable public final net.corda.core.contracts.TimeWindow getTimeWindow() @NotNull @@ -4881,6 +5641,11 @@ public final class net.corda.core.transactions.LedgerTransaction extends net.cor public final java.util.List> inRefsOfType(Class) @NotNull public final java.util.List inputsOfType(Class) + @NotNull + public final java.util.List> referenceInputRefsOfType(Class) + @NotNull + public final java.util.List referenceInputsOfType(Class) + @NotNull public String toString() public final void verify() public static final net.corda.core.transactions.LedgerTransaction$Companion Companion @@ -4903,6 +5668,7 @@ public static final class net.corda.core.transactions.LedgerTransaction$InOutGro @NotNull public final java.util.List getOutputs() public int hashCode() + @NotNull public String toString() ## @CordaSerializable @@ -4940,10 +5706,13 @@ public final class net.corda.core.transactions.NotaryChangeLedgerTransaction ext @NotNull public java.util.List> getOutputs() @NotNull + public java.util.List> getReferences() + @NotNull public java.util.Set getRequiredSigningKeys() @NotNull public java.util.List getSigs() public int hashCode() + @NotNull public String toString() ## @DoNotImplement @@ -4967,12 +5736,15 @@ public final class net.corda.core.transactions.NotaryChangeWireTransaction exten @NotNull public java.util.List> getOutputs() @NotNull + public java.util.List getReferences() + @NotNull public final java.util.List getSerializedComponents() public int hashCode() @NotNull public final net.corda.core.transactions.NotaryChangeLedgerTransaction resolve(net.corda.core.node.ServiceHub, java.util.List) @NotNull public final net.corda.core.transactions.NotaryChangeLedgerTransaction resolve(net.corda.core.node.ServicesForResolution, java.util.List) + @NotNull public String toString() ## public static final class net.corda.core.transactions.NotaryChangeWireTransaction$Component extends java.lang.Enum @@ -5007,6 +5779,8 @@ public final class net.corda.core.transactions.SignedTransaction extends java.la @NotNull public final net.corda.core.transactions.NotaryChangeWireTransaction getNotaryChangeTx() @NotNull + public final java.util.List getReferences() + @NotNull public java.util.Set getRequiredSigningKeys() @NotNull public java.util.List getSigs() @@ -5067,7 +5841,15 @@ public static final class net.corda.core.transactions.SignedTransaction$Signatur public class net.corda.core.transactions.TransactionBuilder extends java.lang.Object public () public (net.corda.core.identity.Party) + public (net.corda.core.identity.Party, java.util.UUID) + public (net.corda.core.identity.Party, java.util.UUID, java.util.List) + public (net.corda.core.identity.Party, java.util.UUID, java.util.List, java.util.List) + public (net.corda.core.identity.Party, java.util.UUID, java.util.List, java.util.List, java.util.List>) + public (net.corda.core.identity.Party, java.util.UUID, java.util.List, java.util.List, java.util.List>, java.util.List>) + public (net.corda.core.identity.Party, java.util.UUID, java.util.List, java.util.List, java.util.List>, java.util.List>, net.corda.core.contracts.TimeWindow) public (net.corda.core.identity.Party, java.util.UUID, java.util.List, java.util.List, java.util.List>, java.util.List>, net.corda.core.contracts.TimeWindow, net.corda.core.contracts.PrivacySalt) + public (net.corda.core.identity.Party, java.util.UUID, java.util.List, java.util.List, java.util.List>, java.util.List>, net.corda.core.contracts.TimeWindow, net.corda.core.contracts.PrivacySalt, java.util.List) + public (net.corda.core.identity.Party, java.util.UUID, java.util.List, java.util.List, java.util.List>, java.util.List>, net.corda.core.contracts.TimeWindow, net.corda.core.contracts.PrivacySalt, java.util.List, net.corda.core.node.ServiceHub) @NotNull public final net.corda.core.transactions.TransactionBuilder addAttachment(net.corda.core.crypto.SecureHash) @NotNull @@ -5079,6 +5861,8 @@ public class net.corda.core.transactions.TransactionBuilder extends java.lang.Ob @NotNull public net.corda.core.transactions.TransactionBuilder addInputState(net.corda.core.contracts.StateAndRef) @NotNull + public final net.corda.core.transactions.TransactionBuilder addOutputState(net.corda.core.contracts.ContractState) + @NotNull public final net.corda.core.transactions.TransactionBuilder addOutputState(net.corda.core.contracts.ContractState, String) @NotNull public final net.corda.core.transactions.TransactionBuilder addOutputState(net.corda.core.contracts.ContractState, String, net.corda.core.contracts.AttachmentConstraint) @@ -5089,8 +5873,12 @@ public class net.corda.core.transactions.TransactionBuilder extends java.lang.Ob @NotNull public final net.corda.core.transactions.TransactionBuilder addOutputState(net.corda.core.contracts.ContractState, String, net.corda.core.identity.Party, Integer, net.corda.core.contracts.AttachmentConstraint) @NotNull + public final net.corda.core.transactions.TransactionBuilder addOutputState(net.corda.core.contracts.ContractState, net.corda.core.identity.Party) + @NotNull public final net.corda.core.transactions.TransactionBuilder addOutputState(net.corda.core.contracts.TransactionState) @NotNull + public net.corda.core.transactions.TransactionBuilder addReferenceState(net.corda.core.contracts.ReferencedStateAndRef) + @NotNull public final java.util.List attachments() @NotNull public final java.util.List> commands() @@ -5110,12 +5898,18 @@ public class net.corda.core.transactions.TransactionBuilder extends java.lang.Ob protected final java.util.List> getOutputs() @NotNull protected final net.corda.core.contracts.PrivacySalt getPrivacySalt() + @NotNull + protected final java.util.List getReferences() + @Nullable + protected final net.corda.core.node.ServiceHub getServiceHub() @Nullable protected final net.corda.core.contracts.TimeWindow getWindow() @NotNull public final java.util.List inputStates() @NotNull public final java.util.List> outputStates() + @NotNull + public final java.util.List referenceStates() public final void setLockId(java.util.UUID) public final void setNotary(net.corda.core.identity.Party) @NotNull @@ -5135,6 +5929,7 @@ public class net.corda.core.transactions.TransactionBuilder extends java.lang.Ob public final void verify(net.corda.core.node.ServiceHub) @NotNull public final net.corda.core.transactions.TransactionBuilder withItems(Object...) + public static final net.corda.core.transactions.TransactionBuilder$Companion Companion ## @DoNotImplement public interface net.corda.core.transactions.TransactionWithSignatures extends net.corda.core.contracts.NamedByHash @@ -5169,12 +5964,16 @@ public abstract class net.corda.core.transactions.TraversableTransaction extends public net.corda.core.identity.Party getNotary() @NotNull public java.util.List> getOutputs() + @NotNull + public java.util.List getReferences() @Nullable public final net.corda.core.contracts.TimeWindow getTimeWindow() ## @DoNotImplement @CordaSerializable public final class net.corda.core.transactions.WireTransaction extends net.corda.core.transactions.TraversableTransaction + public (java.util.List) + public (java.util.List, java.util.List, java.util.List>, java.util.List>, net.corda.core.identity.Party, net.corda.core.contracts.TimeWindow) public (java.util.List, java.util.List, java.util.List>, java.util.List>, net.corda.core.identity.Party, net.corda.core.contracts.TimeWindow, net.corda.core.contracts.PrivacySalt) public (java.util.List, net.corda.core.contracts.PrivacySalt) @NotNull @@ -5213,6 +6012,8 @@ public abstract class net.corda.core.utilities.ByteSequence extends java.lang.Ob public int compareTo(net.corda.core.utilities.ByteSequence) @NotNull public final net.corda.core.utilities.ByteSequence copy() + @NotNull + public final byte[] copyBytes() public boolean equals(Object) @NotNull public abstract byte[] getBytes() @@ -5228,11 +6029,16 @@ public abstract class net.corda.core.utilities.ByteSequence extends java.lang.Ob @NotNull public final java.io.ByteArrayInputStream open() @NotNull + public final java.nio.ByteBuffer putTo(java.nio.ByteBuffer) + @NotNull + public final java.nio.ByteBuffer slice(int, int) + @NotNull public final net.corda.core.utilities.ByteSequence subSequence(int, int) @NotNull public final net.corda.core.utilities.ByteSequence take(int) @NotNull public String toString() + public final void writeTo(java.io.OutputStream) public static final net.corda.core.utilities.ByteSequence$Companion Companion ## public static final class net.corda.core.utilities.ByteSequence$Companion extends java.lang.Object @@ -5309,6 +6115,8 @@ public final class net.corda.core.utilities.KotlinUtilsKt extends java.lang.Obje public static final int exactAdd(int, int) public static final long exactAdd(long, long) @NotNull + public static final java.util.Map filterNotNullValues(java.util.Map) + @NotNull public static final java.time.Duration getDays(int) @NotNull public static final java.time.Duration getHours(int) @@ -5320,10 +6128,13 @@ public final class net.corda.core.utilities.KotlinUtilsKt extends java.lang.Obje @NotNull public static final java.time.Duration getSeconds(int) @NotNull + public static final java.util.List lazyMapped(java.util.List, kotlin.jvm.functions.Function2) + @NotNull public static final net.corda.core.utilities.NonEmptySet toNonEmptySet(java.util.Collection) public static final void trace(org.slf4j.Logger, kotlin.jvm.functions.Function0) @NotNull public static final net.corda.core.utilities.PropertyDelegate transient(kotlin.jvm.functions.Function0) + public static final synchronized void warnOnce(org.slf4j.Logger, String) ## @CordaSerializable public final class net.corda.core.utilities.NetworkHostAndPort extends java.lang.Object @@ -5449,6 +6260,7 @@ public final class net.corda.core.utilities.ProgressTracker extends java.lang.Ob public final net.corda.core.utilities.ProgressTracker$Step nextStep() public final void setChildProgressTracker(net.corda.core.utilities.ProgressTracker$Step, net.corda.core.utilities.ProgressTracker) public final void setCurrentStep(net.corda.core.utilities.ProgressTracker$Step) + public static final net.corda.core.utilities.ProgressTracker$Companion Companion ## @CordaSerializable public abstract static class net.corda.core.utilities.ProgressTracker$Change extends java.lang.Object @@ -5509,12 +6321,21 @@ public static final class net.corda.core.utilities.ProgressTracker$Change$Struct @NotNull public String toString() ## +public static final class net.corda.core.utilities.ProgressTracker$Companion extends java.lang.Object + @NotNull + public final kotlin.jvm.functions.Function0 getDEFAULT_TRACKER() +## @CordaSerializable public static final class net.corda.core.utilities.ProgressTracker$DONE extends net.corda.core.utilities.ProgressTracker$Step public boolean equals(Object) public static final net.corda.core.utilities.ProgressTracker$DONE INSTANCE ## @CordaSerializable +public static final class net.corda.core.utilities.ProgressTracker$STARTING extends net.corda.core.utilities.ProgressTracker$Step + public boolean equals(Object) + public static final net.corda.core.utilities.ProgressTracker$STARTING INSTANCE +## +@CordaSerializable public static class net.corda.core.utilities.ProgressTracker$Step extends java.lang.Object public (String) @Nullable @@ -5534,11 +6355,21 @@ public static final class net.corda.core.utilities.ProgressTracker$UNSTARTED ext public interface net.corda.core.utilities.PropertyDelegate public abstract T getValue(Object, kotlin.reflect.KProperty) ## +public final class net.corda.core.utilities.SgxSupport extends java.lang.Object + public static final boolean isInsideEnclave() + public static final net.corda.core.utilities.SgxSupport INSTANCE +## @CordaSerializable public abstract class net.corda.core.utilities.Try extends java.lang.Object @NotNull public final net.corda.core.utilities.Try combine(net.corda.core.utilities.Try, kotlin.jvm.functions.Function2) @NotNull + public final net.corda.core.utilities.Try doOnException(kotlin.jvm.functions.Function1) + @NotNull + public final net.corda.core.utilities.Try doOnFailure(kotlin.jvm.functions.Function1) + @NotNull + public final net.corda.core.utilities.Try doOnSuccess(kotlin.jvm.functions.Function1) + @NotNull public final net.corda.core.utilities.Try flatMap(kotlin.jvm.functions.Function1>) public abstract A getOrThrow() public abstract boolean isFailure() @@ -5617,6 +6448,8 @@ public final class net.corda.client.jackson.JacksonSupport extends java.lang.Obj @NotNull public static final com.fasterxml.jackson.databind.ObjectMapper createDefaultMapper(net.corda.core.messaging.CordaRPCOps, com.fasterxml.jackson.core.JsonFactory, boolean) @NotNull + public static final com.fasterxml.jackson.databind.ObjectMapper createDefaultMapper(net.corda.core.messaging.CordaRPCOps, com.fasterxml.jackson.core.JsonFactory, boolean, boolean) + @NotNull public static final com.fasterxml.jackson.databind.ObjectMapper createInMemoryMapper(net.corda.core.node.services.IdentityService) @NotNull public static final com.fasterxml.jackson.databind.ObjectMapper createInMemoryMapper(net.corda.core.node.services.IdentityService, com.fasterxml.jackson.core.JsonFactory) @@ -5627,6 +6460,8 @@ public final class net.corda.client.jackson.JacksonSupport extends java.lang.Obj @NotNull public static final com.fasterxml.jackson.databind.ObjectMapper createNonRpcMapper(com.fasterxml.jackson.core.JsonFactory) @NotNull + public static final com.fasterxml.jackson.databind.ObjectMapper createNonRpcMapper(com.fasterxml.jackson.core.JsonFactory, boolean) + @NotNull public final com.fasterxml.jackson.databind.Module getCordaModule() public static final net.corda.client.jackson.JacksonSupport INSTANCE ## @@ -5657,11 +6492,16 @@ public static final class net.corda.client.jackson.JacksonSupport$CordaX500NameS public void serialize(net.corda.core.identity.CordaX500Name, com.fasterxml.jackson.core.JsonGenerator, com.fasterxml.jackson.databind.SerializerProvider) public static final net.corda.client.jackson.JacksonSupport$CordaX500NameSerializer INSTANCE ## +@DoNotImplement public static final class net.corda.client.jackson.JacksonSupport$IdentityObjectMapper extends com.fasterxml.jackson.databind.ObjectMapper implements net.corda.client.jackson.JacksonSupport$PartyObjectMapper public (net.corda.core.node.services.IdentityService, com.fasterxml.jackson.core.JsonFactory, boolean) + public (net.corda.core.node.services.IdentityService, com.fasterxml.jackson.core.JsonFactory, boolean, boolean) public final boolean getFuzzyIdentityMatch() @NotNull public final net.corda.core.node.services.IdentityService getIdentityService() + public boolean isFullParties() + @Nullable + public net.corda.core.node.NodeInfo nodeInfoFromParty(net.corda.core.identity.AbstractParty) @NotNull public java.util.Set partiesFromName(String) @Nullable @@ -5672,6 +6512,10 @@ public static final class net.corda.client.jackson.JacksonSupport$IdentityObject @DoNotImplement public static final class net.corda.client.jackson.JacksonSupport$NoPartyObjectMapper extends com.fasterxml.jackson.databind.ObjectMapper implements net.corda.client.jackson.JacksonSupport$PartyObjectMapper public (com.fasterxml.jackson.core.JsonFactory) + public (com.fasterxml.jackson.core.JsonFactory, boolean) + public boolean isFullParties() + @Nullable + public net.corda.core.node.NodeInfo nodeInfoFromParty(net.corda.core.identity.AbstractParty) @NotNull public java.util.Set partiesFromName(String) @Nullable @@ -5702,7 +6546,11 @@ public static final class net.corda.client.jackson.JacksonSupport$PartyDeseriali public net.corda.core.identity.Party deserialize(com.fasterxml.jackson.core.JsonParser, com.fasterxml.jackson.databind.DeserializationContext) public static final net.corda.client.jackson.JacksonSupport$PartyDeserializer INSTANCE ## +@DoNotImplement public static interface net.corda.client.jackson.JacksonSupport$PartyObjectMapper + public abstract boolean isFullParties() + @Nullable + public abstract net.corda.core.node.NodeInfo nodeInfoFromParty(net.corda.core.identity.AbstractParty) @NotNull public abstract java.util.Set partiesFromName(String) @Nullable @@ -5723,11 +6571,16 @@ public static final class net.corda.client.jackson.JacksonSupport$PublicKeySeria public void serialize(java.security.PublicKey, com.fasterxml.jackson.core.JsonGenerator, com.fasterxml.jackson.databind.SerializerProvider) public static final net.corda.client.jackson.JacksonSupport$PublicKeySerializer INSTANCE ## +@DoNotImplement public static final class net.corda.client.jackson.JacksonSupport$RpcObjectMapper extends com.fasterxml.jackson.databind.ObjectMapper implements net.corda.client.jackson.JacksonSupport$PartyObjectMapper public (net.corda.core.messaging.CordaRPCOps, com.fasterxml.jackson.core.JsonFactory, boolean) + public (net.corda.core.messaging.CordaRPCOps, com.fasterxml.jackson.core.JsonFactory, boolean, boolean) public final boolean getFuzzyIdentityMatch() @NotNull public final net.corda.core.messaging.CordaRPCOps getRpc() + public boolean isFullParties() + @Nullable + public net.corda.core.node.NodeInfo nodeInfoFromParty(net.corda.core.identity.AbstractParty) @NotNull public java.util.Set partiesFromName(String) @Nullable @@ -5869,6 +6722,8 @@ public interface net.corda.testing.driver.DriverDSL @NotNull public abstract net.corda.core.concurrent.CordaFuture startNode(net.corda.testing.driver.NodeParameters, net.corda.core.identity.CordaX500Name, java.util.List, net.corda.testing.driver.VerifierType, java.util.Map, Boolean, String) @NotNull + public abstract net.corda.core.concurrent.CordaFuture startNode(net.corda.testing.driver.NodeParameters, net.corda.core.identity.CordaX500Name, java.util.List, net.corda.testing.driver.VerifierType, java.util.Map, Boolean, String, java.util.Collection, boolean, java.util.Map>, ? extends Class>>) + @NotNull public abstract net.corda.core.concurrent.CordaFuture startWebserver(net.corda.testing.driver.NodeHandle) @NotNull public abstract net.corda.core.concurrent.CordaFuture startWebserver(net.corda.testing.driver.NodeHandle, String) @@ -5876,8 +6731,11 @@ public interface net.corda.testing.driver.DriverDSL public final class net.corda.testing.driver.DriverParameters extends java.lang.Object public () public (boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map, boolean, boolean, boolean, java.util.List, java.util.List, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters) + public (boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map, boolean, boolean, boolean, java.util.List, java.util.List, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Collection) public (boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map, boolean, boolean, boolean, java.util.List, java.util.List, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Map, boolean, boolean) + public (boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map, boolean, boolean, boolean, java.util.List, java.util.List, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Map, boolean, boolean, java.util.Collection, boolean) public (boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map, boolean, boolean, boolean, java.util.List, java.util.List, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, boolean, boolean) + public (boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map, boolean, boolean, boolean, java.util.List, java.util.List, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, boolean, boolean, java.util.Set) public final boolean component1() @NotNull public final java.util.List component10() @@ -5886,6 +6744,13 @@ public final class net.corda.testing.driver.DriverParameters extends java.lang.O @NotNull public final net.corda.core.node.NetworkParameters component12() @NotNull + public final java.util.Map component13() + public final boolean component14() + public final boolean component15() + @Nullable + public final java.util.Collection component16() + public final boolean component17() + @NotNull public final java.nio.file.Path component2() @NotNull public final net.corda.testing.driver.PortAllocation component3() @@ -5900,18 +6765,33 @@ public final class net.corda.testing.driver.DriverParameters extends java.lang.O public final java.util.List component9() @NotNull public final net.corda.testing.driver.DriverParameters copy(boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map, boolean, boolean, boolean, java.util.List, java.util.List, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters) + @NotNull + public final net.corda.testing.driver.DriverParameters copy(boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map, boolean, boolean, boolean, java.util.List, java.util.List, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Map, boolean, boolean, java.util.Collection, boolean) + @NotNull + public final net.corda.testing.driver.DriverParameters copy(boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map, boolean, boolean, boolean, java.util.List, java.util.List, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Set) + @NotNull + public final net.corda.testing.driver.DriverParameters copy(boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map, boolean, boolean, boolean, java.util.List, java.util.List, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, boolean) + @NotNull + public final net.corda.testing.driver.DriverParameters copy(boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map, boolean, boolean, boolean, java.util.List, java.util.List, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, boolean, java.util.Set) public boolean equals(Object) + @Nullable + public final java.util.Collection getCordappsForAllNodes() @NotNull public final net.corda.testing.driver.PortAllocation getDebugPortAllocation() @NotNull public final java.nio.file.Path getDriverDirectory() + public final boolean getEnableSNI() @NotNull public final java.util.List getExtraCordappPackagesToScan() + public final boolean getInMemoryDB() + public final boolean getInitialiseSerialization() @NotNull public final net.corda.testing.driver.JmxPolicy getJmxPolicy() @NotNull public final net.corda.core.node.NetworkParameters getNetworkParameters() @NotNull + public final java.util.Map getNotaryCustomOverrides() + @NotNull public final java.util.List getNotarySpecs() @NotNull public final net.corda.testing.driver.PortAllocation getPortAllocation() @@ -5922,20 +6802,29 @@ public final class net.corda.testing.driver.DriverParameters extends java.lang.O public final boolean getWaitForAllNodesToFinish() public int hashCode() public final boolean isDebug() + @NotNull public String toString() @NotNull + public final net.corda.testing.driver.DriverParameters withCordappsForAllNodes(java.util.Collection) + @NotNull public final net.corda.testing.driver.DriverParameters withDebugPortAllocation(net.corda.testing.driver.PortAllocation) @NotNull public final net.corda.testing.driver.DriverParameters withDriverDirectory(java.nio.file.Path) @NotNull public final net.corda.testing.driver.DriverParameters withExtraCordappPackagesToScan(java.util.List) @NotNull + public final net.corda.testing.driver.DriverParameters withInMemoryDB(boolean) + @NotNull + public final net.corda.testing.driver.DriverParameters withInitialiseSerialization(boolean) + @NotNull public final net.corda.testing.driver.DriverParameters withIsDebug(boolean) @NotNull public final net.corda.testing.driver.DriverParameters withJmxPolicy(net.corda.testing.driver.JmxPolicy) @NotNull public final net.corda.testing.driver.DriverParameters withNetworkParameters(net.corda.core.node.NetworkParameters) @NotNull + public final net.corda.testing.driver.DriverParameters withNotaryCustomOverrides(java.util.Map) + @NotNull public final net.corda.testing.driver.DriverParameters withNotarySpecs(java.util.List) @NotNull public final net.corda.testing.driver.DriverParameters withPortAllocation(net.corda.testing.driver.PortAllocation) @@ -5970,6 +6859,7 @@ public final class net.corda.testing.driver.JmxPolicy extends java.lang.Object public final net.corda.testing.driver.PortAllocation getJmxHttpServerPortAllocation() public final boolean getStartJmxHttpServer() public int hashCode() + @NotNull public String toString() ## @DoNotImplement @@ -5985,15 +6875,22 @@ public interface net.corda.testing.driver.NodeHandle extends java.lang.AutoClose @NotNull public abstract net.corda.core.utilities.NetworkHostAndPort getRpcAddress() @NotNull + public abstract net.corda.core.utilities.NetworkHostAndPort getRpcAdminAddress() + @NotNull public abstract java.util.List getRpcUsers() public abstract void stop() ## public final class net.corda.testing.driver.NodeParameters extends java.lang.Object public () public (net.corda.core.identity.CordaX500Name, java.util.List, net.corda.testing.driver.VerifierType, java.util.Map, Boolean, String) + public (net.corda.core.identity.CordaX500Name, java.util.List, net.corda.testing.driver.VerifierType, java.util.Map, Boolean, String, String) + public (net.corda.core.identity.CordaX500Name, java.util.List, net.corda.testing.driver.VerifierType, java.util.Map, Boolean, String, String, java.util.Collection, boolean, java.util.Map>, ? extends Class>>) + public (net.corda.core.identity.CordaX500Name, java.util.List, net.corda.testing.driver.VerifierType, java.util.Map, Boolean, String, java.util.Set, boolean) @Nullable public final net.corda.core.identity.CordaX500Name component1() @NotNull + public final java.util.Map>, Class>> component10() + @NotNull public final java.util.List component2() @NotNull public final net.corda.testing.driver.VerifierType component3() @@ -6003,15 +6900,31 @@ public final class net.corda.testing.driver.NodeParameters extends java.lang.Obj public final Boolean component5() @NotNull public final String component6() + @Nullable + public final String component7() + @NotNull + public final java.util.Collection component8() + public final boolean component9() @NotNull public final net.corda.testing.driver.NodeParameters copy(net.corda.core.identity.CordaX500Name, java.util.List, net.corda.testing.driver.VerifierType, java.util.Map, Boolean, String) + @NotNull + public final net.corda.testing.driver.NodeParameters copy(net.corda.core.identity.CordaX500Name, java.util.List, net.corda.testing.driver.VerifierType, java.util.Map, Boolean, String, String) + @NotNull + public final net.corda.testing.driver.NodeParameters copy(net.corda.core.identity.CordaX500Name, java.util.List, net.corda.testing.driver.VerifierType, java.util.Map, Boolean, String, String, java.util.Collection, boolean, java.util.Map>, ? extends Class>>) public boolean equals(Object) @NotNull + public final java.util.Collection getAdditionalCordapps() + @NotNull public final java.util.Map getCustomOverrides() @NotNull + public final java.util.Map>, Class>> getFlowOverrides() + @Nullable + public final String getLogLevel() + @NotNull public final String getMaximumHeapSize() @Nullable public final net.corda.core.identity.CordaX500Name getProvidedName() + public final boolean getRegenerateCordappsOnStart() @NotNull public final java.util.List getRpcUsers() @Nullable @@ -6019,10 +6932,17 @@ public final class net.corda.testing.driver.NodeParameters extends java.lang.Obj @NotNull public final net.corda.testing.driver.VerifierType getVerifierType() public int hashCode() + @NotNull public String toString() @NotNull + public final net.corda.testing.driver.NodeParameters withAdditionalCordapps(java.util.Set) + @NotNull public final net.corda.testing.driver.NodeParameters withCustomOverrides(java.util.Map) @NotNull + public final net.corda.testing.driver.NodeParameters withDeleteExistingCordappsDirectory(boolean) + @NotNull + public final net.corda.testing.driver.NodeParameters withLogLevel(String) + @NotNull public final net.corda.testing.driver.NodeParameters withMaximumHeapSize(String) @NotNull public final net.corda.testing.driver.NodeParameters withProvidedName(net.corda.core.identity.CordaX500Name) @@ -6049,6 +6969,7 @@ public final class net.corda.testing.driver.NotaryHandle extends java.lang.Objec public final net.corda.core.concurrent.CordaFuture> getNodeHandles() public final boolean getValidating() public int hashCode() + @NotNull public String toString() ## @DoNotImplement @@ -6089,6 +7010,7 @@ public final class net.corda.testing.driver.WebserverHandle extends java.lang.Ob @NotNull public final Process getProcess() public int hashCode() + @NotNull public String toString() ## @DoNotImplement @@ -6105,6 +7027,7 @@ public static final class net.corda.testing.node.ClusterSpec$Raft extends net.co public boolean equals(Object) public int getClusterSize() public int hashCode() + @NotNull public String toString() ## @ThreadSafe @@ -6194,10 +7117,51 @@ public static final class net.corda.testing.node.InMemoryMessagingNetwork$Servic public () public A pickNext(net.corda.testing.node.InMemoryMessagingNetwork$DistributedServiceHandle, java.util.List) ## +public final class net.corda.testing.node.MockNetFlowTimeOut extends java.lang.Object + public (java.time.Duration, int, double) + @NotNull + public final java.time.Duration component1() + public final int component2() + public final double component3() + @NotNull + public final net.corda.testing.node.MockNetFlowTimeOut copy(java.time.Duration, int, double) + public boolean equals(Object) + public final double getBackoffBase() + public final int getMaxRestartCount() + @NotNull + public final java.time.Duration getTimeout() + public int hashCode() + @NotNull + public String toString() +## +public final class net.corda.testing.node.MockNetNotaryConfig extends java.lang.Object + public (boolean, com.typesafe.config.Config, String, net.corda.core.identity.CordaX500Name) + public final boolean component1() + @Nullable + public final com.typesafe.config.Config component2() + @Nullable + public final String component3() + @Nullable + public final net.corda.core.identity.CordaX500Name component4() + @NotNull + public final net.corda.testing.node.MockNetNotaryConfig copy(boolean, com.typesafe.config.Config, String, net.corda.core.identity.CordaX500Name) + public boolean equals(Object) + @Nullable + public final String getClassName() + @Nullable + public final com.typesafe.config.Config getExtraConfig() + @Nullable + public final net.corda.core.identity.CordaX500Name getServiceLegalName() + public final boolean getValidating() + public int hashCode() + @NotNull + public String toString() +## public class net.corda.testing.node.MockNetwork extends java.lang.Object public (java.util.List) public (java.util.List, net.corda.testing.node.MockNetworkParameters) public (java.util.List, net.corda.testing.node.MockNetworkParameters, boolean, boolean, net.corda.testing.node.InMemoryMessagingNetwork$ServicePeerAllocationStrategy, java.util.List, net.corda.core.node.NetworkParameters) + public (java.util.List, net.corda.testing.node.MockNetworkParameters, boolean, boolean, net.corda.testing.node.InMemoryMessagingNetwork$ServicePeerAllocationStrategy, java.util.List, net.corda.core.node.NetworkParameters, java.util.Collection) @NotNull public final java.nio.file.Path baseDirectory(int) @NotNull @@ -6209,6 +7173,12 @@ public class net.corda.testing.node.MockNetwork extends java.lang.Object @NotNull public final net.corda.testing.node.StartedMockNode createNode(net.corda.core.identity.CordaX500Name, Integer, java.math.BigInteger) @NotNull + public final net.corda.testing.node.StartedMockNode createNode(net.corda.core.identity.CordaX500Name, Integer, java.math.BigInteger, net.corda.testing.node.MockNodeConfigOverrides) + @NotNull + public final net.corda.testing.node.StartedMockNode createNode(net.corda.core.identity.CordaX500Name, Integer, java.math.BigInteger, net.corda.testing.node.MockNodeConfigOverrides, java.util.Collection) + @NotNull + public final net.corda.testing.node.StartedMockNode createNode(net.corda.core.identity.CordaX500Name, Integer, java.math.BigInteger, net.corda.testing.node.MockNodeConfigOverrides, java.util.List) + @NotNull public final net.corda.testing.node.StartedMockNode createNode(net.corda.testing.node.MockNodeParameters) @NotNull public final net.corda.testing.node.StartedMockNode createPartyNode(net.corda.core.identity.CordaX500Name) @@ -6221,10 +7191,18 @@ public class net.corda.testing.node.MockNetwork extends java.lang.Object @NotNull public final net.corda.testing.node.UnstartedMockNode createUnstartedNode(net.corda.core.identity.CordaX500Name, Integer, java.math.BigInteger) @NotNull + public final net.corda.testing.node.UnstartedMockNode createUnstartedNode(net.corda.core.identity.CordaX500Name, Integer, java.math.BigInteger, net.corda.testing.node.MockNodeConfigOverrides) + @NotNull + public final net.corda.testing.node.UnstartedMockNode createUnstartedNode(net.corda.core.identity.CordaX500Name, Integer, java.math.BigInteger, net.corda.testing.node.MockNodeConfigOverrides, java.util.Collection) + @NotNull + public final net.corda.testing.node.UnstartedMockNode createUnstartedNode(net.corda.core.identity.CordaX500Name, Integer, java.math.BigInteger, net.corda.testing.node.MockNodeConfigOverrides, java.util.List) + @NotNull public final net.corda.testing.node.UnstartedMockNode createUnstartedNode(net.corda.testing.node.MockNodeParameters) @NotNull public final java.util.List getCordappPackages() @NotNull + public final java.util.Collection getCordappsForAllNodes() + @NotNull public final net.corda.core.identity.Party getDefaultNotaryIdentity() @NotNull public final net.corda.testing.node.StartedMockNode getDefaultNotaryNode() @@ -6247,6 +7225,8 @@ public class net.corda.testing.node.MockNetwork extends java.lang.Object public final void stopNodes() public final void waitQuiescent() ## +public final class net.corda.testing.node.MockNetworkKt extends java.lang.Object +## public final class net.corda.testing.node.MockNetworkNotarySpec extends java.lang.Object public (net.corda.core.identity.CordaX500Name) public (net.corda.core.identity.CordaX500Name, boolean) @@ -6260,6 +7240,7 @@ public final class net.corda.testing.node.MockNetworkNotarySpec extends java.lan public final net.corda.core.identity.CordaX500Name getName() public final boolean getValidating() public int hashCode() + @NotNull public String toString() ## public final class net.corda.testing.node.MockNetworkParameters extends java.lang.Object @@ -6285,6 +7266,7 @@ public final class net.corda.testing.node.MockNetworkParameters extends java.lan public final net.corda.testing.node.InMemoryMessagingNetwork$ServicePeerAllocationStrategy getServicePeerAllocationStrategy() public final boolean getThreadPerNode() public int hashCode() + @NotNull public String toString() @NotNull public final net.corda.testing.node.MockNetworkParameters withNetworkParameters(net.corda.core.node.NetworkParameters) @@ -6297,24 +7279,65 @@ public final class net.corda.testing.node.MockNetworkParameters extends java.lan @NotNull public final net.corda.testing.node.MockNetworkParameters withThreadPerNode(boolean) ## +public final class net.corda.testing.node.MockNodeConfigOverrides extends java.lang.Object + public () + public (java.util.Map, net.corda.testing.node.MockNetNotaryConfig, net.corda.testing.node.MockNetFlowTimeOut) + @Nullable + public final java.util.Map component1() + @Nullable + public final net.corda.testing.node.MockNetNotaryConfig component2() + @Nullable + public final net.corda.testing.node.MockNetFlowTimeOut component3() + @NotNull + public final net.corda.testing.node.MockNodeConfigOverrides copy(java.util.Map, net.corda.testing.node.MockNetNotaryConfig, net.corda.testing.node.MockNetFlowTimeOut) + public boolean equals(Object) + @Nullable + public final java.util.Map getExtraDataSourceProperties() + @Nullable + public final net.corda.testing.node.MockNetFlowTimeOut getFlowTimeout() + @Nullable + public final net.corda.testing.node.MockNetNotaryConfig getNotary() + public int hashCode() + @NotNull + public String toString() +## public final class net.corda.testing.node.MockNodeParameters extends java.lang.Object public () + public (Integer, net.corda.core.identity.CordaX500Name, java.math.BigInteger, net.corda.testing.node.MockNodeConfigOverrides) + public (Integer, net.corda.core.identity.CordaX500Name, java.math.BigInteger, net.corda.testing.node.MockNodeConfigOverrides, java.util.Collection) @Nullable public final Integer component1() @Nullable public final net.corda.core.identity.CordaX500Name component2() @NotNull public final java.math.BigInteger component3() + @Nullable + public final net.corda.testing.node.MockNodeConfigOverrides component4() + @NotNull + public final java.util.Collection component5() + @NotNull + public final net.corda.testing.node.MockNodeParameters copy(Integer, net.corda.core.identity.CordaX500Name, java.math.BigInteger, net.corda.testing.node.MockNodeConfigOverrides) + @NotNull + public final net.corda.testing.node.MockNodeParameters copy(Integer, net.corda.core.identity.CordaX500Name, java.math.BigInteger, net.corda.testing.node.MockNodeConfigOverrides, java.util.Collection) public boolean equals(Object) @NotNull + public final java.util.Collection getAdditionalCordapps() + @Nullable + public final net.corda.testing.node.MockNodeConfigOverrides getConfigOverrides() + @NotNull public final java.math.BigInteger getEntropyRoot() @Nullable public final Integer getForcedID() @Nullable public final net.corda.core.identity.CordaX500Name getLegalName() public int hashCode() + @NotNull public String toString() @NotNull + public final net.corda.testing.node.MockNodeParameters withAdditionalCordapps(java.util.Collection) + @NotNull + public final net.corda.testing.node.MockNodeParameters withConfigOverrides(net.corda.testing.node.MockNodeConfigOverrides) + @NotNull public final net.corda.testing.node.MockNodeParameters withEntropyRoot(java.math.BigInteger) @NotNull public final net.corda.testing.node.MockNodeParameters withForcedID(Integer) @@ -6331,6 +7354,7 @@ public class net.corda.testing.node.MockServices extends java.lang.Object implem public (Iterable, net.corda.testing.core.TestIdentity, net.corda.core.node.services.IdentityService, net.corda.core.node.NetworkParameters, java.security.KeyPair...) public (Iterable, net.corda.testing.core.TestIdentity, net.corda.core.node.services.IdentityService, java.security.KeyPair...) public (Iterable, net.corda.testing.core.TestIdentity, java.security.KeyPair...) + public (java.util.List, net.corda.testing.core.TestIdentity, net.corda.testing.core.TestIdentity...) public (net.corda.core.identity.CordaX500Name) public (net.corda.core.identity.CordaX500Name, java.security.KeyPair, java.security.KeyPair...) public (net.corda.core.identity.CordaX500Name, net.corda.core.node.services.IdentityService) @@ -6352,6 +7376,8 @@ public class net.corda.testing.node.MockServices extends java.lang.Object implem @NotNull public net.corda.core.crypto.TransactionSignature createSignature(net.corda.core.transactions.SignedTransaction, java.security.PublicKey) @NotNull + public net.corda.core.cordapp.CordappContext getAppContext() + @NotNull public final net.corda.testing.services.MockAttachmentStorage getAttachments() @NotNull public net.corda.testing.node.TestClock getClock() @@ -6404,6 +7430,9 @@ public class net.corda.testing.node.MockServices extends java.lang.Object implem public net.corda.core.transactions.SignedTransaction signInitialTransaction(net.corda.core.transactions.TransactionBuilder, java.security.PublicKey) @NotNull public net.corda.core.contracts.StateAndRef toStateAndRef(net.corda.core.contracts.StateRef) + public void withEntityManager(java.util.function.Consumer) + @NotNull + public T withEntityManager(kotlin.jvm.functions.Function1) public static final net.corda.testing.node.MockServices$Companion Companion ## public static final class net.corda.testing.node.MockServices$Companion extends java.lang.Object @@ -6458,6 +7487,7 @@ public final class net.corda.testing.node.NotarySpec extends java.lang.Object @NotNull public final net.corda.testing.driver.VerifierType getVerifierType() public int hashCode() + @NotNull public String toString() ## public interface net.corda.testing.node.ResponderFlowFactory @@ -6477,6 +7507,8 @@ public final class net.corda.testing.node.StartedMockNode extends java.lang.Obje @NotNull public final rx.Observable registerInitiatedFlow(Class) @NotNull + public final net.corda.core.concurrent.CordaFuture registerResponderFlow(Class>, net.corda.testing.node.ResponderFlowFactory, Class) + @NotNull public final net.corda.core.concurrent.CordaFuture startFlow(net.corda.core.flows.FlowLogic) public final void stop() public final T transaction(kotlin.jvm.functions.Function0) @@ -6490,9 +7522,54 @@ public final class net.corda.testing.node.TestClock extends net.corda.node.Mutab public final synchronized void advanceBy(java.time.Duration) public final synchronized void setTo(java.time.Instant) ## +@DoNotImplement +public interface net.corda.testing.node.TestCordapp + @NotNull + public abstract java.util.Map getConfig() + @NotNull + public abstract String getName() + @NotNull + public abstract java.util.Set getPackages() + public abstract int getTargetVersion() + @NotNull + public abstract String getTitle() + @NotNull + public abstract String getVendor() + @NotNull + public abstract String getVersion() + @NotNull + public abstract net.corda.testing.node.TestCordapp withConfig(java.util.Map) + @NotNull + public abstract net.corda.testing.node.TestCordapp withName(String) + @NotNull + public abstract net.corda.testing.node.TestCordapp withTargetVersion(int) + @NotNull + public abstract net.corda.testing.node.TestCordapp withTitle(String) + @NotNull + public abstract net.corda.testing.node.TestCordapp withVendor(String) + @NotNull + public abstract net.corda.testing.node.TestCordapp withVersion(String) +## +public static final class net.corda.testing.node.TestCordapp$Factory extends java.lang.Object + public () + @NotNull + public static final net.corda.testing.node.TestCordapp fromPackages(java.util.Collection) + @NotNull + public static final net.corda.testing.node.TestCordapp fromPackages(String...) + public static final net.corda.testing.node.TestCordapp$Factory$Companion Companion +## +public static final class net.corda.testing.node.TestCordapp$Factory$Companion extends java.lang.Object + @NotNull + public final net.corda.testing.node.TestCordapp fromPackages(java.util.Collection) + @NotNull + public final net.corda.testing.node.TestCordapp fromPackages(String...) +## public final class net.corda.testing.node.UnstartedMockNode extends java.lang.Object public final int getId() @NotNull + public final net.corda.testing.node.StartedMockNode getStarted() + public final boolean isStarted() + @NotNull public final net.corda.testing.node.StartedMockNode start() public static final net.corda.testing.node.UnstartedMockNode$Companion Companion ## @@ -6516,8 +7593,13 @@ public final class net.corda.testing.node.User extends java.lang.Object @NotNull public final String getUsername() public int hashCode() + @NotNull public String toString() ## +public class net.corda.client.rpc.ConnectionFailureException extends net.corda.client.rpc.RPCException + public () + public (Throwable) +## public final class net.corda.client.rpc.CordaRPCClient extends java.lang.Object public (java.util.List) public (java.util.List, net.corda.client.rpc.CordaRPCClientConfiguration) @@ -6527,6 +7609,10 @@ public final class net.corda.client.rpc.CordaRPCClient extends java.lang.Object public final net.corda.client.rpc.CordaRPCConnection start(String, String) @NotNull public final net.corda.client.rpc.CordaRPCConnection start(String, String, net.corda.core.context.Trace, net.corda.core.context.Actor) + @NotNull + public final net.corda.client.rpc.CordaRPCConnection start(String, String, net.corda.core.context.Trace, net.corda.core.context.Actor, net.corda.core.identity.CordaX500Name) + @NotNull + public final net.corda.client.rpc.CordaRPCConnection start(String, String, net.corda.core.identity.CordaX500Name) public final A use(String, String, kotlin.jvm.functions.Function1) public static final net.corda.client.rpc.CordaRPCClient$Companion Companion ## @@ -6537,15 +7623,62 @@ public static final class net.corda.client.rpc.CordaRPCClient$Companion extends public final net.corda.client.rpc.CordaRPCClient createWithSsl(net.corda.core.utilities.NetworkHostAndPort, net.corda.core.messaging.ClientRpcSslOptions, net.corda.client.rpc.CordaRPCClientConfiguration) ## public class net.corda.client.rpc.CordaRPCClientConfiguration extends java.lang.Object + public () public (java.time.Duration) + public (java.time.Duration, int) + public (java.time.Duration, int, boolean) + public (java.time.Duration, int, boolean, java.time.Duration) + public (java.time.Duration, int, boolean, java.time.Duration, int) + public (java.time.Duration, int, boolean, java.time.Duration, int, int) + public (java.time.Duration, int, boolean, java.time.Duration, int, int, java.time.Duration) + public (java.time.Duration, int, boolean, java.time.Duration, int, int, java.time.Duration, double) + public (java.time.Duration, int, boolean, java.time.Duration, int, int, java.time.Duration, double, int) + public (java.time.Duration, int, boolean, java.time.Duration, int, int, java.time.Duration, double, int, int) + public (java.time.Duration, int, boolean, java.time.Duration, int, int, java.time.Duration, double, int, int, java.time.Duration) @NotNull public final java.time.Duration component1() @NotNull + public final net.corda.client.rpc.CordaRPCClientConfiguration copy() + @NotNull public final net.corda.client.rpc.CordaRPCClientConfiguration copy(java.time.Duration) + @NotNull + public final net.corda.client.rpc.CordaRPCClientConfiguration copy(java.time.Duration, int) + @NotNull + public final net.corda.client.rpc.CordaRPCClientConfiguration copy(java.time.Duration, int, boolean) + @NotNull + public final net.corda.client.rpc.CordaRPCClientConfiguration copy(java.time.Duration, int, boolean, java.time.Duration) + @NotNull + public final net.corda.client.rpc.CordaRPCClientConfiguration copy(java.time.Duration, int, boolean, java.time.Duration, int) + @NotNull + public final net.corda.client.rpc.CordaRPCClientConfiguration copy(java.time.Duration, int, boolean, java.time.Duration, int, int) + @NotNull + public final net.corda.client.rpc.CordaRPCClientConfiguration copy(java.time.Duration, int, boolean, java.time.Duration, int, int, java.time.Duration) + @NotNull + public final net.corda.client.rpc.CordaRPCClientConfiguration copy(java.time.Duration, int, boolean, java.time.Duration, int, int, java.time.Duration, double) + @NotNull + public final net.corda.client.rpc.CordaRPCClientConfiguration copy(java.time.Duration, int, boolean, java.time.Duration, int, int, java.time.Duration, double, int) + @NotNull + public final net.corda.client.rpc.CordaRPCClientConfiguration copy(java.time.Duration, int, boolean, java.time.Duration, int, int, java.time.Duration, double, int, int) + @NotNull + public final net.corda.client.rpc.CordaRPCClientConfiguration copy(java.time.Duration, int, boolean, java.time.Duration, int, int, java.time.Duration, double, int, int, java.time.Duration) public boolean equals(Object) + public int getCacheConcurrencyLevel() @NotNull public java.time.Duration getConnectionMaxRetryInterval() + @NotNull + public java.time.Duration getConnectionRetryInterval() + public double getConnectionRetryIntervalMultiplier() + @NotNull + public java.time.Duration getDeduplicationCacheExpiry() + public int getMaxFileSize() + public int getMaxReconnectAttempts() + public int getMinimumServerProtocolVersion() + public int getObservationExecutorPoolSize() + @NotNull + public java.time.Duration getReapInterval() + public boolean getTrackRpcCallSites() public int hashCode() + @NotNull public String toString() public static final net.corda.client.rpc.CordaRPCClientConfiguration$Companion Companion @NotNull @@ -6603,6 +7736,7 @@ public final class net.corda.testing.contracts.DummyContract extends java.lang.O public static final net.corda.core.transactions.TransactionBuilder move(java.util.List>, net.corda.core.identity.AbstractParty) @NotNull public static final net.corda.core.transactions.TransactionBuilder move(net.corda.core.contracts.StateAndRef, net.corda.core.identity.AbstractParty) + @NotNull public String toString() public void verify(net.corda.core.transactions.LedgerTransaction) public static final net.corda.testing.contracts.DummyContract$Companion Companion @@ -6640,6 +7774,7 @@ public static final class net.corda.testing.contracts.DummyContract$MultiOwnerSt @NotNull public java.util.List getParticipants() public int hashCode() + @NotNull public String toString() ## @DoNotImplement @@ -6657,6 +7792,7 @@ public static final class net.corda.testing.contracts.DummyContract$SingleOwnerS @NotNull public java.util.List getParticipants() public int hashCode() + @NotNull public String toString() @NotNull public net.corda.core.contracts.CommandAndState withNewOwner(net.corda.core.identity.AbstractParty) @@ -6702,19 +7838,67 @@ public static final class net.corda.testing.contracts.DummyContractV2$State exte @NotNull public java.util.List getParticipants() public int hashCode() + @NotNull public String toString() ## +public final class net.corda.testing.contracts.DummyContractV3 extends java.lang.Object implements net.corda.core.contracts.UpgradedContractWithLegacyConstraint + public () + @NotNull + public String getLegacyContract() + @NotNull + public net.corda.core.contracts.AttachmentConstraint getLegacyContractConstraint() + @NotNull + public net.corda.testing.contracts.DummyContractV3$State upgrade(net.corda.testing.contracts.DummyContractV2$State) + public void verify(net.corda.core.transactions.LedgerTransaction) + public static final net.corda.testing.contracts.DummyContractV3$Companion Companion + @NotNull + public static final String PROGRAM_ID = "net.corda.testing.contracts.DummyContractV3" +## +public static interface net.corda.testing.contracts.DummyContractV3$Commands extends net.corda.core.contracts.CommandData +## +public static final class net.corda.testing.contracts.DummyContractV3$Commands$Create extends net.corda.core.contracts.TypeOnlyCommandData implements net.corda.testing.contracts.DummyContractV3$Commands + public () +## +public static final class net.corda.testing.contracts.DummyContractV3$Commands$Move extends net.corda.core.contracts.TypeOnlyCommandData implements net.corda.testing.contracts.DummyContractV3$Commands + public () +## +public static final class net.corda.testing.contracts.DummyContractV3$Companion extends java.lang.Object +## +public static final class net.corda.testing.contracts.DummyContractV3$State extends java.lang.Object implements net.corda.core.contracts.ContractState + public (int, java.util.List) + public final int component1() + @NotNull + public final java.util.List component2() + @NotNull + public final net.corda.testing.contracts.DummyContractV3$State copy(int, java.util.List) + public boolean equals(Object) + public final int getMagicNumber() + @NotNull + public final java.util.List getOwners() + @NotNull + public java.util.List getParticipants() + public int hashCode() + @NotNull + public String toString() +## +@BelongsToContract public final class net.corda.testing.contracts.DummyState extends java.lang.Object implements net.corda.core.contracts.ContractState public () public (int) + public (int, java.util.List) public final int component1() @NotNull + public final java.util.List component2() + @NotNull public final net.corda.testing.contracts.DummyState copy(int) + @NotNull + public final net.corda.testing.contracts.DummyState copy(int, java.util.List) public boolean equals(Object) public final int getMagicNumber() @NotNull public java.util.List getParticipants() public int hashCode() + @NotNull public String toString() ## public final class net.corda.testing.core.DummyCommandData extends net.corda.core.contracts.TypeOnlyCommandData @@ -6738,6 +7922,7 @@ public final class net.corda.testing.core.Expect extends java.lang.Object @NotNull public final kotlin.jvm.functions.Function1 getMatch() public int hashCode() + @NotNull public String toString() ## @DoNotImplement @@ -6821,6 +8006,20 @@ public final class net.corda.testing.core.ExpectKt extends java.lang.Object @NotNull public static final net.corda.testing.core.ExpectCompose sequence(net.corda.testing.core.ExpectCompose...) ## +public final class net.corda.testing.core.JarSignatureTestUtils extends java.lang.Object + public final void addIndexList(java.nio.file.Path, String) + public final void createJar(java.nio.file.Path, String, String...) + public final void executeProcess(java.nio.file.Path, String...) + public final void generateKey(java.nio.file.Path, String, String, String, String, String, String) + @NotNull + public final java.nio.file.Path getBin() + @NotNull + public final java.util.List getJarSigners(java.nio.file.Path, String) + @NotNull + public final java.security.PublicKey signJar(java.nio.file.Path, String, String, String, String) + public final void updateJar(java.nio.file.Path, String, String...) + public static final net.corda.testing.core.JarSignatureTestUtils INSTANCE +## public final class net.corda.testing.core.SerializationEnvironmentRule extends java.lang.Object implements org.junit.rules.TestRule public () public (boolean) @@ -6857,7 +8056,13 @@ public final class net.corda.testing.core.TestConstants extends java.lang.Object public final class net.corda.testing.core.TestIdentity extends java.lang.Object public (net.corda.core.identity.CordaX500Name) public (net.corda.core.identity.CordaX500Name, long) + public (net.corda.core.identity.CordaX500Name, long, net.corda.core.crypto.SignatureScheme) public (net.corda.core.identity.CordaX500Name, java.security.KeyPair) + public (net.corda.core.identity.CordaX500Name, net.corda.core.crypto.SignatureScheme) + @NotNull + public static final net.corda.testing.core.TestIdentity fresh(String) + @NotNull + public static final net.corda.testing.core.TestIdentity fresh(String, net.corda.core.crypto.SignatureScheme) @NotNull public final net.corda.core.identity.PartyAndCertificate getIdentity() @NotNull @@ -6875,6 +8080,8 @@ public final class net.corda.testing.core.TestIdentity extends java.lang.Object public static final class net.corda.testing.core.TestIdentity$Companion extends java.lang.Object @NotNull public final net.corda.testing.core.TestIdentity fresh(String) + @NotNull + public final net.corda.testing.core.TestIdentity fresh(String, net.corda.core.crypto.SignatureScheme) ## public final class net.corda.testing.core.TestUtils extends java.lang.Object @NotNull @@ -6889,10 +8096,41 @@ public final class net.corda.testing.core.TestUtils extends java.lang.Object @NotNull public static final net.corda.core.identity.PartyAndCertificate getTestPartyAndCertificate(net.corda.core.identity.Party) @NotNull + public static final net.corda.core.identity.CordaX500Name makeUnique(net.corda.core.identity.CordaX500Name) + @NotNull + public static final java.util.Collection product(java.util.Collection, java.util.Collection) + @NotNull public static final net.corda.core.identity.Party singleIdentity(net.corda.core.node.NodeInfo) @NotNull public static final net.corda.core.identity.PartyAndCertificate singleIdentityAndCert(net.corda.core.node.NodeInfo) ## +public final class net.corda.testing.database.DatabaseConstants extends java.lang.Object + @NotNull + public static final String DATA_SOURCE_CLASSNAME = "dataSourceProperties.dataSourceClassName" + @NotNull + public static final String DATA_SOURCE_PASSWORD = "dataSourceProperties.dataSource.password" + @NotNull + public static final String DATA_SOURCE_URL = "dataSourceProperties.dataSource.url" + @NotNull + public static final String DATA_SOURCE_USER = "dataSourceProperties.dataSource.user" + public static final net.corda.testing.database.DatabaseConstants INSTANCE + @NotNull + public static final String SCHEMA = "database.schema" + @NotNull + public static final String TRANSACTION_ISOLATION_LEVEL = "database.transactionIsolationLevel" +## +public final class net.corda.testing.database.DbScriptRunner extends java.lang.Object + @NotNull + public final java.util.List merge(java.util.List, String) + @NotNull + public final java.util.List merge(java.util.List, java.util.List) + public final void runDbScript(String, String, java.util.List) + public static final net.corda.testing.database.DbScriptRunner INSTANCE +## +public final class net.corda.testing.database.ListPopulator extends java.lang.Object implements org.springframework.jdbc.datasource.init.DatabasePopulator + public (boolean, boolean, java.util.List) + public void populate(java.sql.Connection) +## public final class net.corda.testing.dsl.AttachmentResolutionException extends net.corda.core.flows.FlowException public (net.corda.core.crypto.SecureHash) ## @@ -6996,6 +8234,7 @@ public final class net.corda.testing.dsl.TestLedgerDSLInterpreter extends java.l public final String outputToLabel(net.corda.core.contracts.ContractState) @NotNull public net.corda.core.contracts.StateAndRef retrieveOutputStateAndRef(Class, String) + @NotNull public String toString() @Nullable public final String transactionName(net.corda.core.crypto.SecureHash) @@ -7029,12 +8268,14 @@ public static final class net.corda.testing.dsl.TestLedgerDSLInterpreter$WireTra @NotNull public final net.corda.core.transactions.WireTransaction getTransaction() public int hashCode() + @NotNull public String toString() ## @DoNotImplement public final class net.corda.testing.dsl.TestTransactionDSLInterpreter extends java.lang.Object implements net.corda.testing.dsl.TransactionDSLInterpreter, net.corda.testing.dsl.OutputStateLookup public (net.corda.testing.dsl.TestLedgerDSLInterpreter, net.corda.core.transactions.TransactionBuilder) public void _attachment(String) + public void _attachment(String, net.corda.core.crypto.SecureHash, java.util.List) @NotNull public net.corda.testing.dsl.EnforceVerifyOrFail _tweak(kotlin.jvm.functions.Function1) public void attachment(net.corda.core.crypto.SecureHash) @@ -7061,9 +8302,11 @@ public final class net.corda.testing.dsl.TestTransactionDSLInterpreter extends j public int hashCode() public void input(net.corda.core.contracts.StateRef) public void output(String, String, net.corda.core.identity.Party, Integer, net.corda.core.contracts.AttachmentConstraint, net.corda.core.contracts.ContractState) + public void reference(net.corda.core.contracts.StateRef) @NotNull public net.corda.core.contracts.StateAndRef retrieveOutputStateAndRef(Class, String) public void timeWindow(net.corda.core.contracts.TimeWindow) + @NotNull public String toString() @NotNull public net.corda.testing.dsl.EnforceVerifyOrFail verifies() @@ -7072,9 +8315,12 @@ public final class net.corda.testing.dsl.TestTransactionDSLInterpreter extends j public final class net.corda.testing.dsl.TransactionDSL extends java.lang.Object implements net.corda.testing.dsl.TransactionDSLInterpreter public (T, net.corda.core.identity.Party) public void _attachment(String) + public void _attachment(String, net.corda.core.crypto.SecureHash, java.util.List) @NotNull public net.corda.testing.dsl.EnforceVerifyOrFail _tweak(kotlin.jvm.functions.Function1) public final void attachment(String) + public final void attachment(String, net.corda.core.crypto.SecureHash) + public final void attachment(String, net.corda.core.crypto.SecureHash, java.util.List) public void attachment(net.corda.core.crypto.SecureHash) public final void attachments(String...) public final void command(java.security.PublicKey, net.corda.core.contracts.CommandData) @@ -7088,6 +8334,7 @@ public final class net.corda.testing.dsl.TransactionDSL extends java.lang.Object @NotNull public net.corda.testing.dsl.LedgerDSLInterpreter getLedgerInterpreter() public final void input(String) + public final void input(String, String) public final void input(String, net.corda.core.contracts.ContractState) public void input(net.corda.core.contracts.StateRef) public final void output(String, int, net.corda.core.contracts.ContractState) @@ -7097,6 +8344,9 @@ public final class net.corda.testing.dsl.TransactionDSL extends java.lang.Object public final void output(String, String, net.corda.core.identity.Party, net.corda.core.contracts.ContractState) public final void output(String, net.corda.core.contracts.ContractState) public final void output(String, net.corda.core.identity.Party, net.corda.core.contracts.ContractState) + public final void reference(String) + public final void reference(String, net.corda.core.contracts.ContractState) + public void reference(net.corda.core.contracts.StateRef) @NotNull public net.corda.core.contracts.StateAndRef retrieveOutputStateAndRef(Class, String) public final void timeWindow(java.time.Instant) @@ -7110,6 +8360,7 @@ public final class net.corda.testing.dsl.TransactionDSL extends java.lang.Object @DoNotImplement public interface net.corda.testing.dsl.TransactionDSLInterpreter extends net.corda.testing.dsl.OutputStateLookup, net.corda.testing.dsl.Verifies public abstract void _attachment(String) + public abstract void _attachment(String, net.corda.core.crypto.SecureHash, java.util.List) @NotNull public abstract net.corda.testing.dsl.EnforceVerifyOrFail _tweak(kotlin.jvm.functions.Function1) public abstract void attachment(net.corda.core.crypto.SecureHash) @@ -7118,6 +8369,7 @@ public interface net.corda.testing.dsl.TransactionDSLInterpreter extends net.cor public abstract net.corda.testing.dsl.LedgerDSLInterpreter getLedgerInterpreter() public abstract void input(net.corda.core.contracts.StateRef) public abstract void output(String, String, net.corda.core.identity.Party, Integer, net.corda.core.contracts.AttachmentConstraint, net.corda.core.contracts.ContractState) + public abstract void reference(net.corda.core.contracts.StateRef) public abstract void timeWindow(net.corda.core.contracts.TimeWindow) ## @DoNotImplement @@ -7168,6 +8420,10 @@ public final class net.corda.testing.services.MockAttachmentStorage extends net. @NotNull public final net.corda.core.crypto.SecureHash importContractAttachment(java.util.List, String, java.io.InputStream) @NotNull + public final net.corda.core.crypto.SecureHash importContractAttachment(java.util.List, String, java.io.InputStream, net.corda.core.crypto.SecureHash) + @NotNull + public final net.corda.core.crypto.SecureHash importContractAttachment(java.util.List, String, java.io.InputStream, net.corda.core.crypto.SecureHash, java.util.List) + @NotNull public net.corda.core.crypto.SecureHash importOrGetAttachment(java.io.InputStream) @Nullable public net.corda.core.contracts.Attachment openAttachment(net.corda.core.crypto.SecureHash) diff --git a/confidential-identities/src/main/kotlin/net/corda/confidential/SwapIdentitiesFlow.kt b/confidential-identities/src/main/kotlin/net/corda/confidential/SwapIdentitiesFlow.kt index bac9a523e2..b3da56637a 100644 --- a/confidential-identities/src/main/kotlin/net/corda/confidential/SwapIdentitiesFlow.kt +++ b/confidential-identities/src/main/kotlin/net/corda/confidential/SwapIdentitiesFlow.kt @@ -28,6 +28,9 @@ import java.util.* */ @StartableByRPC @InitiatingFlow +// TODO Make this non-initiating as otherwise any CorDapp using confidential identities will cause its node to have an +// open door where any counterparty will be able to swap identities at will. Instead SwapIdentitiesFlow and its counterpart, +// SwapIdentitiesHandler, should be in-lined and called by CorDapp specfic-flows. class SwapIdentitiesFlow(private val otherParty: Party, private val revocationEnabled: Boolean, override val progressTracker: ProgressTracker) : FlowLogic>() { diff --git a/confidential-identities/src/test/kotlin/net/corda/confidential/IdentitySyncFlowTests.kt b/confidential-identities/src/test/kotlin/net/corda/confidential/IdentitySyncFlowTests.kt index bf9bb223da..fa9879aeab 100644 --- a/confidential-identities/src/test/kotlin/net/corda/confidential/IdentitySyncFlowTests.kt +++ b/confidential-identities/src/test/kotlin/net/corda/confidential/IdentitySyncFlowTests.kt @@ -18,8 +18,8 @@ import net.corda.testing.core.ALICE_NAME import net.corda.testing.core.BOB_NAME import net.corda.testing.core.CHARLIE_NAME import net.corda.testing.core.singleIdentity +import net.corda.testing.node.internal.FINANCE_CORDAPP import net.corda.testing.node.internal.InternalMockNetwork -import net.corda.testing.node.internal.cordappsForPackages import net.corda.testing.node.internal.startFlow import org.junit.After import org.junit.Before @@ -35,7 +35,7 @@ class IdentitySyncFlowTests { fun before() { // We run this in parallel threads to help catch any race conditions that may exist. mockNet = InternalMockNetwork( - cordappsForAllNodes = cordappsForPackages("net.corda.finance.contracts.asset", "net.corda.finance.schemas"), + cordappsForAllNodes = listOf(FINANCE_CORDAPP), networkSendManuallyPumped = false, threadPerNode = true ) diff --git a/core/src/main/kotlin/net/corda/core/flows/CollectSignaturesFlow.kt b/core/src/main/kotlin/net/corda/core/flows/CollectSignaturesFlow.kt index 7e0d98efb4..aab20f5e78 100644 --- a/core/src/main/kotlin/net/corda/core/flows/CollectSignaturesFlow.kt +++ b/core/src/main/kotlin/net/corda/core/flows/CollectSignaturesFlow.kt @@ -187,9 +187,9 @@ class CollectSignatureFlow(val partiallySignedTx: SignedTransaction, val session * } * * // Invoke the subFlow, in response to the counterparty calling [CollectSignaturesFlow]. - * val stx = subFlow(flow) + * val expectedTxId = subFlow(flow).id * - * return waitForLedgerCommit(stx.id) + * return subFlow(ReceiveFinalityFlow(otherPartySession, expectedTxId)) * } * } * diff --git a/core/src/main/kotlin/net/corda/core/flows/FinalityFlow.kt b/core/src/main/kotlin/net/corda/core/flows/FinalityFlow.kt index 15512bb13c..5a01712d55 100644 --- a/core/src/main/kotlin/net/corda/core/flows/FinalityFlow.kt +++ b/core/src/main/kotlin/net/corda/core/flows/FinalityFlow.kt @@ -1,10 +1,14 @@ package net.corda.core.flows import co.paralleluniverse.fibers.Suspendable +import net.corda.core.crypto.SecureHash import net.corda.core.crypto.isFulfilledBy import net.corda.core.identity.Party import net.corda.core.identity.groupAbstractPartyByWellKnownParty +import net.corda.core.internal.cordapp.CordappInfoResolver import net.corda.core.internal.pushToLoggingContext +import net.corda.core.node.StatesToRecord +import net.corda.core.node.StatesToRecord.ONLY_RELEVANT import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.ProgressTracker @@ -17,23 +21,53 @@ import net.corda.core.utilities.ProgressTracker * The transaction is expected to have already been resolved: if its dependencies are not available in local * storage, verification will fail. It must have signatures from all necessary parties other than the notary. * - * If specified, the extra recipients are sent the given transaction. The base set of parties to inform are calculated - * from the contract-given set of participants. + * A list of [FlowSession]s is required for each non-local participant of the transaction. These participants will receive + * the final notarised transaction by calling [ReceiveFinalityFlow] in their counterpart flows. Sessions with non-participants + * can also be included, but they must specifiy [StatesToRecord.ALL_VISIBLE] for statesToRecortd if they wish to record the + * contract states into their vaults. * * The flow returns the same transaction but with the additional signatures from the notary. * + * NOTE: This is an inlined flow but for backwards compatibility is annotated with [InitiatingFlow]. + * * @param transaction What to commit. - * @param extraRecipients A list of additional participants to inform of the transaction. + * @param sessions A collection of [FlowSession]s who will be given the notarised transaction. This list **must** include + * all participants in the transaction (excluding the local identity). */ +// To maintain backwards compatibility with the old API, FinalityFlow can act both as an intiating flow and as an inlined flow. +// This is only possible because a flow is only truly initiating when the first call to initiateFlow is made (where the +// presence of @InitiatingFlow is checked). So the new API is inlined simply because that code path doesn't call initiateFlow. @InitiatingFlow -class FinalityFlow(val transaction: SignedTransaction, - private val extraRecipients: Set, - override val progressTracker: ProgressTracker) : FlowLogic() { - constructor(transaction: SignedTransaction, extraParticipants: Set) : this(transaction, extraParticipants, tracker()) - constructor(transaction: SignedTransaction) : this(transaction, emptySet(), tracker()) - constructor(transaction: SignedTransaction, progressTracker: ProgressTracker) : this(transaction, emptySet(), progressTracker) +class FinalityFlow private constructor(val transaction: SignedTransaction, + private val extraRecipients: Set, + override val progressTracker: ProgressTracker, + private val sessions: Collection?) : FlowLogic() { + @Deprecated(DEPRECATION_MSG) + constructor(transaction: SignedTransaction, extraRecipients: Set, progressTracker: ProgressTracker) : this( + transaction, extraRecipients, progressTracker, null + ) + @Deprecated(DEPRECATION_MSG) + constructor(transaction: SignedTransaction, extraRecipients: Set) : this(transaction, extraRecipients, tracker(), null) + @Deprecated(DEPRECATION_MSG) + constructor(transaction: SignedTransaction) : this(transaction, emptySet(), tracker(), null) + @Deprecated(DEPRECATION_MSG) + constructor(transaction: SignedTransaction, progressTracker: ProgressTracker) : this(transaction, emptySet(), progressTracker, null) + + constructor(transaction: SignedTransaction, sessions: Collection, progressTracker: ProgressTracker) : this( + transaction, emptySet(), progressTracker, sessions + ) + constructor(transaction: SignedTransaction, sessions: Collection) : this( + transaction, emptySet(), tracker(), sessions + ) + constructor(transaction: SignedTransaction, firstSession: FlowSession, vararg restSessions: FlowSession) : this( + transaction, emptySet(), tracker(), listOf(firstSession) + restSessions.asList() + ) companion object { + private const val DEPRECATION_MSG = "It is unsafe to use this constructor as it requires nodes to automatically " + + "accept notarised transactions without first checking their relevancy. Instead, use one of the constructors " + + "that takes in existing FlowSessions." + object NOTARISING : ProgressTracker.Step("Requesting signature by notary service") { override fun childProgressTracker() = NotaryFlow.Client.tracker() } @@ -47,6 +81,19 @@ class FinalityFlow(val transaction: SignedTransaction, @Suspendable @Throws(NotaryException::class) override fun call(): SignedTransaction { + if (sessions == null) { + require(CordappInfoResolver.currentTargetVersion < 4) { + "A flow session for each external participant to the transaction must be provided. If you wish to continue " + + "using this insecure API then specify a target platform version of less than 4 for your CorDapp." + } + logger.warn("The current usage of FinalityFlow is unsafe. Please consider upgrading your CorDapp to use " + + "FinalityFlow with FlowSessions.") + } else { + require(sessions.none { serviceHub.myInfo.isLegalIdentity(it.counterparty) }) { + "Do not provide flow sessions for the local node. FinalityFlow will record the notarised transaction locally." + } + } + // Note: this method is carefully broken up to minimize the amount of data reachable from the stack at // the point where subFlow is invoked, as that minimizes the checkpointing work to be done. // @@ -54,26 +101,49 @@ class FinalityFlow(val transaction: SignedTransaction, // Then send to the notary if needed, record locally and distribute. transaction.pushToLoggingContext() - val commandDataTypes = transaction.tx.commands.map { it.value }.mapNotNull { it::class.qualifiedName }.distinct() - logger.info("Started finalization, commands are ${commandDataTypes.joinToString(", ", "[", "]")}.") - val parties = getPartiesToSend(verifyTx()) + logCommandData() + val externalParticipants = extractExternalParticipants(verifyTx()) + + if (sessions != null) { + val missingRecipients = externalParticipants - sessions.map { it.counterparty } + require(missingRecipients.isEmpty()) { + "Flow sessions were not provided for the following transaction participants: $missingRecipients" + } + } + val notarised = notariseAndRecord() // Each transaction has its own set of recipients, but extra recipients get them all. progressTracker.currentStep = BROADCASTING - val recipients = parties.filterNot(serviceHub.myInfo::isLegalIdentity) - logger.info("Broadcasting transaction to parties ${recipients.map { it.name }.joinToString(", ", "[", "]")}.") - for (party in recipients) { - logger.info("Sending transaction to party ${party.name}.") - val session = initiateFlow(party) - subFlow(SendTransactionFlow(session, notarised)) - logger.info("Party ${party.name} received the transaction.") + + if (sessions == null) { + val recipients = externalParticipants + (extraRecipients - serviceHub.myInfo.legalIdentities) + logger.info("Broadcasting transaction to parties ${recipients.joinToString(", ", "[", "]")}.") + for (recipient in recipients) { + logger.info("Sending transaction to party ${recipient.name}.") + val session = initiateFlow(recipient) + subFlow(SendTransactionFlow(session, notarised)) + logger.info("Party $recipient received the transaction.") + } + } else { + for (session in sessions) { + subFlow(SendTransactionFlow(session, notarised)) + logger.info("Party ${session.counterparty} received the transaction.") + } } + logger.info("All parties received the transaction successfully.") return notarised } + private fun logCommandData() { + if (logger.isDebugEnabled) { + val commandDataTypes = transaction.tx.commands.asSequence().mapNotNull { it.value::class.qualifiedName }.distinct() + logger.debug("Started finalization, commands are ${commandDataTypes.joinToString(", ", "[", "]")}.") + } + } + @Suspendable private fun notariseAndRecord(): SignedTransaction { val notarised = if (needsNotarySignature(transaction)) { @@ -98,13 +168,13 @@ class FinalityFlow(val transaction: SignedTransaction, private fun hasNoNotarySignature(stx: SignedTransaction): Boolean { val notaryKey = stx.tx.notary?.owningKey - val signers = stx.sigs.map { it.by }.toSet() + val signers = stx.sigs.asSequence().map { it.by }.toSet() return notaryKey?.isFulfilledBy(signers) != true } - private fun getPartiesToSend(ltx: LedgerTransaction): Set { + private fun extractExternalParticipants(ltx: LedgerTransaction): Set { val participants = ltx.outputStates.flatMap { it.participants } + ltx.inputStates.flatMap { it.participants } - return groupAbstractPartyByWellKnownParty(serviceHub, participants).keys + extraRecipients + return groupAbstractPartyByWellKnownParty(serviceHub, participants).keys - serviceHub.myInfo.legalIdentities } private fun verifyTx(): LedgerTransaction { @@ -116,3 +186,33 @@ class FinalityFlow(val transaction: SignedTransaction, return ltx } } + +/** + * The receiving counterpart to [FinalityFlow]. + * + * All parties who are receiving a finalised transaction from a sender flow must subcall this flow in their own flows. + * + * It's typical to have already signed the transaction proposal in the same workflow using [SignTransactionFlow]. If so + * then the transaction ID can be passed in as an extra check to ensure the finalised transaction is the one that was signed + * before it's committed to the vault. + * + * @param otherSideSession The session which is providing the transaction to record. + * @param expectedTxId Expected ID of the transaction that's about to be received. This is typically retrieved from + * [SignTransactionFlow]. + * @param statesToRecord Which transactions to commit to the vault. Defaults to [StatesToRecord.ONLY_RELEVANT]. + */ +class ReceiveFinalityFlow @JvmOverloads constructor(val otherSideSession: FlowSession, + val expectedTxId: SecureHash? = null, + val statesToRecord: StatesToRecord = ONLY_RELEVANT) : FlowLogic() { + @Suspendable + override fun call(): SignedTransaction { + return subFlow(object : ReceiveTransactionFlow(otherSideSession, checkSufficientSignatures = true, statesToRecord = statesToRecord) { + override fun checkBeforeRecording(stx: SignedTransaction) { + require(expectedTxId == null || expectedTxId == stx.id) { + "We expected to receive transaction with ID $expectedTxId but instead got ${stx.id}. Transaction was" + + "not recorded and nor its states sent to the vault." + } + } + }) + } +} diff --git a/core/src/main/kotlin/net/corda/core/flows/ReceiveTransactionFlow.kt b/core/src/main/kotlin/net/corda/core/flows/ReceiveTransactionFlow.kt index 0267d5764d..56d2376e36 100644 --- a/core/src/main/kotlin/net/corda/core/flows/ReceiveTransactionFlow.kt +++ b/core/src/main/kotlin/net/corda/core/flows/ReceiveTransactionFlow.kt @@ -23,9 +23,9 @@ import java.security.SignatureException * @property checkSufficientSignatures if true checks all required signatures are present. See [SignedTransaction.verify]. * @property statesToRecord which transaction states should be recorded in the vault, if any. */ -class ReceiveTransactionFlow @JvmOverloads constructor(private val otherSideSession: FlowSession, - private val checkSufficientSignatures: Boolean = true, - private val statesToRecord: StatesToRecord = StatesToRecord.NONE) : FlowLogic() { +open class ReceiveTransactionFlow @JvmOverloads constructor(private val otherSideSession: FlowSession, + private val checkSufficientSignatures: Boolean = true, + private val statesToRecord: StatesToRecord = StatesToRecord.NONE) : FlowLogic() { @Suppress("KDocMissingDocumentation") @Suspendable @Throws(SignatureException::class, @@ -40,7 +40,7 @@ class ReceiveTransactionFlow @JvmOverloads constructor(private val otherSideSess } val stx = otherSideSession.receive().unwrap { it.pushToLoggingContext() - logger.info("Received transaction acknowledgement request from party ${otherSideSession.counterparty.name}.") + logger.info("Received transaction acknowledgement request from party ${otherSideSession.counterparty}.") subFlow(ResolveTransactionsFlow(it, otherSideSession)) logger.info("Transaction dependencies resolution completed.") try { @@ -54,12 +54,21 @@ class ReceiveTransactionFlow @JvmOverloads constructor(private val otherSideSess if (checkSufficientSignatures) { // We should only send a transaction to the vault for processing if we did in fact fully verify it, and // there are no missing signatures. We don't want partly signed stuff in the vault. + checkBeforeRecording(stx) logger.info("Successfully received fully signed tx. Sending it to the vault for processing.") serviceHub.recordTransactions(statesToRecord, setOf(stx)) logger.info("Successfully recorded received transaction locally.") } return stx } + + /** + * Hook to perform extra checks on the received transaction just before it's recorded. The transaction has already + * been resolved and verified at this point. + */ + @Suspendable + @Throws(FlowException::class) + protected open fun checkBeforeRecording(stx: SignedTransaction) = Unit } /** @@ -74,7 +83,8 @@ class ReceiveStateAndRefFlow(private val otherSideSession @Suspendable override fun call(): List> { return otherSideSession.receive>>().unwrap { - subFlow(ResolveTransactionsFlow(it.map { it.ref.txhash }.toSet(), otherSideSession)) + val txHashes = it.asSequence().map { it.ref.txhash }.toSet() + subFlow(ResolveTransactionsFlow(txHashes, otherSideSession)) it } } diff --git a/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappInfoResolver.kt b/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappInfoResolver.kt index 63f7cb2188..8a2253d062 100644 --- a/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappInfoResolver.kt +++ b/core/src/main/kotlin/net/corda/core/internal/cordapp/CordappInfoResolver.kt @@ -1,5 +1,6 @@ package net.corda.core.internal.cordapp +import net.corda.core.internal.PLATFORM_VERSION import net.corda.core.internal.VisibleForTesting import net.corda.core.utilities.loggerFor import java.util.concurrent.ConcurrentHashMap @@ -11,12 +12,12 @@ object CordappInfoResolver { private val logger = loggerFor() private val cordappClasses: ConcurrentHashMap> = ConcurrentHashMap() - // TODO use the StackWalker API once we migrate to Java 9+ + // TODO Use the StackWalker API once we migrate to Java 9+ private var cordappInfoResolver: () -> CordappImpl.Info? = { Exception().stackTrace .mapNotNull { cordappClasses[it.className] } // If there is more than one cordapp registered for a class name we can't determine the "correct" one and return null. - .firstOrNull { it.size < 2 }?.single() + .firstOrNull { it.size == 1 }?.single() } /* @@ -42,22 +43,33 @@ object CordappInfoResolver { * In situations where a `[CordappProvider]` is available the CorDapp context should be obtained from there. * * @return Information about the CorDapp from which the invoker is called, null if called outside a CorDapp or the - * calling CorDapp cannot be reliably determined.. + * calling CorDapp cannot be reliably determined. */ - fun getCorDappInfo(): CordappImpl.Info? = cordappInfoResolver() + val currentCordappInfo: CordappImpl.Info? get() = cordappInfoResolver() /** - * Temporarily switch out the internal resolver for another one. For use in testing. + * Returns the target version of the current calling CorDapp. Defaults to the current platform version if there isn't one. + */ + // TODO It may be the default is wrong and this should be Int? instead + val currentTargetVersion: Int get() = currentCordappInfo?.targetPlatformVersion ?: PLATFORM_VERSION + + /** + * Temporarily apply a fake CorDapp.Info with the given parameters. For use in testing. */ @Synchronized @VisibleForTesting - fun withCordappInfoResolution(tempResolver: () -> CordappImpl.Info?, block: () -> Unit) { - val resolver = cordappInfoResolver - cordappInfoResolver = tempResolver + fun withCordappInfo(shortName: String = "CordappInfoResolver.withCordappInfo", + vendor: String = "Corda", + version: String = "1.0", + minimumPlatformVersion: Int = 1, + targetPlatformVersion: Int = PLATFORM_VERSION, + block: () -> T): T { + val currentResolver = cordappInfoResolver + cordappInfoResolver = { CordappImpl.Info(shortName, vendor, version, minimumPlatformVersion, targetPlatformVersion) } try { - block() + return block() } finally { - cordappInfoResolver = resolver + cordappInfoResolver = currentResolver } } @@ -65,4 +77,4 @@ object CordappInfoResolver { internal fun clear() { cordappClasses.clear() } -} \ No newline at end of file +} diff --git a/core/src/test/kotlin/net/corda/core/flows/CollectSignaturesFlowTests.kt b/core/src/test/kotlin/net/corda/core/flows/CollectSignaturesFlowTests.kt index c8bf1fad7a..12112d3460 100644 --- a/core/src/test/kotlin/net/corda/core/flows/CollectSignaturesFlowTests.kt +++ b/core/src/test/kotlin/net/corda/core/flows/CollectSignaturesFlowTests.kt @@ -5,8 +5,6 @@ import com.natpryce.hamkrest.assertion.assert import net.corda.core.contracts.Command import net.corda.core.contracts.StateAndContract import net.corda.core.contracts.requireThat -import net.corda.testing.internal.matchers.flow.willReturn -import net.corda.testing.internal.matchers.flow.willThrow import net.corda.core.flows.mixins.WithContracts import net.corda.core.identity.CordaX500Name import net.corda.core.identity.Party @@ -17,6 +15,8 @@ import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder import net.corda.testing.contracts.DummyContract import net.corda.testing.core.* +import net.corda.testing.internal.matchers.flow.willReturn +import net.corda.testing.internal.matchers.flow.willThrow import net.corda.testing.internal.rigorousMock import net.corda.testing.node.MockServices import net.corda.testing.node.internal.InternalMockNetwork @@ -116,7 +116,7 @@ class CollectSignaturesFlowTests : WithContracts { val ptx = serviceHub.signInitialTransaction(builder) val sessions = excludeHostNode(serviceHub, groupAbstractPartyByWellKnownParty(serviceHub, state.owners)).map { initiateFlow(it.key) } val stx = subFlow(CollectSignaturesFlow(ptx, sessions, myInputKeys)) - return subFlow(FinalityFlow(stx)) + return subFlow(FinalityFlow(stx, sessions)) } } @@ -136,8 +136,8 @@ class CollectSignaturesFlowTests : WithContracts { } } - val stx = subFlow(signFlow) - waitForLedgerCommit(stx.id) + val stxId = subFlow(signFlow).id + subFlow(ReceiveFinalityFlow(otherSideSession, expectedTxId = stxId)) } } } diff --git a/core/src/test/kotlin/net/corda/core/flows/FinalityFlowTests.kt b/core/src/test/kotlin/net/corda/core/flows/FinalityFlowTests.kt index fd8ceab510..d5cf4ab5f6 100644 --- a/core/src/test/kotlin/net/corda/core/flows/FinalityFlowTests.kt +++ b/core/src/test/kotlin/net/corda/core/flows/FinalityFlowTests.kt @@ -4,63 +4,98 @@ import com.natpryce.hamkrest.and import com.natpryce.hamkrest.assertion.assert import net.corda.core.flows.mixins.WithFinality import net.corda.core.identity.Party +import net.corda.core.internal.cordapp.CordappInfoResolver import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder +import net.corda.core.utilities.getOrThrow import net.corda.finance.POUNDS import net.corda.finance.contracts.asset.Cash import net.corda.finance.issuedBy import net.corda.testing.core.* import net.corda.testing.internal.matchers.flow.willReturn import net.corda.testing.internal.matchers.flow.willThrow -import net.corda.testing.node.internal.InternalMockNetwork -import net.corda.testing.node.internal.TestStartedNode -import net.corda.testing.node.internal.cordappsForPackages -import org.junit.AfterClass +import net.corda.testing.node.TestCordapp +import net.corda.testing.node.internal.* +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatIllegalArgumentException +import org.junit.After import org.junit.Test class FinalityFlowTests : WithFinality { companion object { private val CHARLIE = TestIdentity(CHARLIE_NAME, 90).party - private val classMockNet = InternalMockNetwork(cordappsForAllNodes = cordappsForPackages( - "net.corda.finance.contracts.asset", - "net.corda.finance.schemas" - )) - - @JvmStatic - @AfterClass - fun tearDown() = classMockNet.stopNodes() } - override val mockNet = classMockNet + override val mockNet = InternalMockNetwork(cordappsForAllNodes = cordappsForPackages( + "net.corda.finance.contracts.asset", + "net.corda.finance.schemas", + "net.corda.core.flows.mixins" + )) private val aliceNode = makeNode(ALICE_NAME) - private val bobNode = makeNode(BOB_NAME) - private val bob = bobNode.info.singleIdentity() private val notary = mockNet.defaultNotaryIdentity + @After + fun tearDown() = mockNet.stopNodes() + @Test fun `finalise a simple transaction`() { - val stx = aliceNode.signCashTransactionWith(bob) + val bob = createBob() + val stx = aliceNode.issuesCashTo(bob) assert.that( - aliceNode.finalise(stx), + aliceNode.finalise(stx, bob.info.singleIdentity()), willReturn( requiredSignatures(1) - and visibleTo(bobNode))) + and visibleTo(bob))) } @Test fun `reject a transaction with unknown parties`() { // Charlie isn't part of this network, so node A won't recognise them - val stx = aliceNode.signCashTransactionWith(CHARLIE) + val stx = aliceNode.issuesCashTo(CHARLIE) assert.that( aliceNode.finalise(stx), willThrow()) } - private fun TestStartedNode.signCashTransactionWith(other: Party): SignedTransaction { + @Test + fun `prevent use of the old API if the CorDapp target version is 4`() { + val bob = createBob() + val stx = aliceNode.issuesCashTo(bob) + val resultFuture = CordappInfoResolver.withCordappInfo(targetPlatformVersion = 4) { + @Suppress("DEPRECATION") + aliceNode.startFlowAndRunNetwork(FinalityFlow(stx)).resultFuture + } + assertThatIllegalArgumentException().isThrownBy { + resultFuture.getOrThrow() + }.withMessageContaining("A flow session for each external participant to the transaction must be provided.") + } + + @Test + fun `allow use of the old API if the CorDapp target version is 3`() { + // We need Bob to load at least one old CorDapp so that its FinalityHandler is enabled + val bob = createBob(cordapps = listOf(cordappForPackages("com.template").withTargetVersion(3))) + val stx = aliceNode.issuesCashTo(bob) + val resultFuture = CordappInfoResolver.withCordappInfo(targetPlatformVersion = 3) { + @Suppress("DEPRECATION") + aliceNode.startFlowAndRunNetwork(FinalityFlow(stx)).resultFuture + } + resultFuture.getOrThrow() + assertThat(bob.services.validatedTransactions.getTransaction(stx.id)).isNotNull() + } + + private fun createBob(cordapps: List = emptyList()): TestStartedNode { + return mockNet.createNode(InternalMockNodeParameters(legalName = BOB_NAME, additionalCordapps = cordapps)) + } + + private fun TestStartedNode.issuesCashTo(recipient: TestStartedNode): SignedTransaction { + return issuesCashTo(recipient.info.singleIdentity()) + } + + private fun TestStartedNode.issuesCashTo(other: Party): SignedTransaction { val amount = 1000.POUNDS.issuedBy(info.singleIdentity().ref(0)) val builder = TransactionBuilder(notary) Cash().generateIssue(builder, amount, other, notary) diff --git a/core/src/test/kotlin/net/corda/core/flows/WithReferencedStatesFlowTests.kt b/core/src/test/kotlin/net/corda/core/flows/WithReferencedStatesFlowTests.kt index 16be871aa0..deb07d0089 100644 --- a/core/src/test/kotlin/net/corda/core/flows/WithReferencedStatesFlowTests.kt +++ b/core/src/test/kotlin/net/corda/core/flows/WithReferencedStatesFlowTests.kt @@ -50,7 +50,7 @@ internal class CreateRefState : FlowLogic() { addOutputState(RefState.State(ourIdentity), RefState.CONTRACT_ID) addCommand(RefState.Create(), listOf(ourIdentity.owningKey)) }) - return subFlow(FinalityFlow(stx)) + return subFlow(FinalityFlow(stx, emptyList())) } } @@ -64,7 +64,7 @@ internal class UpdateRefState(private val stateAndRef: StateAndRef { - return startFlowAndRunNetwork(FinalityFlow(stx, additionalParties.toSet())) + fun TestStartedNode.finalise(stx: SignedTransaction, vararg recipients: Party): FlowStateMachine { + return startFlowAndRunNetwork(FinalityInvoker(stx, recipients.toSet())) } fun TestStartedNode.getValidatedTransaction(stx: SignedTransaction): SignedTransaction { return services.validatedTransactions.getTransaction(stx.id)!! } - fun CordaRPCOps.finalise(stx: SignedTransaction, vararg parties: Party): FlowHandle { - return startFlow(::FinalityInvoker, stx, parties.toSet()).andRunNetwork() + fun CordaRPCOps.finalise(stx: SignedTransaction, vararg recipients: Party): FlowHandle { + return startFlow(::FinalityInvoker, stx, recipients.toSet()).andRunNetwork() } //endregion @@ -40,10 +38,22 @@ interface WithFinality : WithMockNet { } //endregion + @InitiatingFlow @StartableByRPC class FinalityInvoker(private val transaction: SignedTransaction, - private val extraRecipients: Set) : FlowLogic() { + private val recipients: Set) : FlowLogic() { @Suspendable - override fun call(): SignedTransaction = subFlow(FinalityFlow(transaction, extraRecipients)) + override fun call(): SignedTransaction { + val sessions = recipients.map(::initiateFlow) + return subFlow(FinalityFlow(transaction, sessions)) + } + } + + @InitiatedBy(FinalityInvoker::class) + class FinalityResponder(private val otherSide: FlowSession) : FlowLogic() { + @Suspendable + override fun call() { + subFlow(ReceiveFinalityFlow(otherSide)) + } } } diff --git a/core/src/test/kotlin/net/corda/core/internal/cordapp/CordappInfoResolverTest.kt b/core/src/test/kotlin/net/corda/core/internal/cordapp/CordappInfoResolverTest.kt index 2ae7403e1a..1a28785094 100644 --- a/core/src/test/kotlin/net/corda/core/internal/cordapp/CordappInfoResolverTest.kt +++ b/core/src/test/kotlin/net/corda/core/internal/cordapp/CordappInfoResolverTest.kt @@ -1,42 +1,37 @@ package net.corda.core.internal.cordapp +import org.assertj.core.api.Assertions.assertThat import org.junit.After import org.junit.Before import org.junit.Test import kotlin.test.assertEquals class CordappInfoResolverTest { - @Before @After fun clearCordappInfoResolver() { CordappInfoResolver.clear() } - @Test() - fun `The correct cordapp resolver is used after calling withCordappResolution`() { + @Test + fun `the correct cordapp resolver is used after calling withCordappInfo`() { val defaultTargetVersion = 222 CordappInfoResolver.register(listOf(javaClass.name), CordappImpl.Info("test", "test", "2", 3, defaultTargetVersion)) - assertEquals(defaultTargetVersion, returnCallingTargetVersion()) + assertEquals(defaultTargetVersion, CordappInfoResolver.currentTargetVersion) val expectedTargetVersion = 555 - CordappInfoResolver.withCordappInfoResolution( { CordappImpl.Info("foo", "bar", "1", 2, expectedTargetVersion) }) - { - val actualTargetVersion = returnCallingTargetVersion() + CordappInfoResolver.withCordappInfo(targetPlatformVersion = expectedTargetVersion) { + val actualTargetVersion = CordappInfoResolver.currentTargetVersion assertEquals(expectedTargetVersion, actualTargetVersion) } - assertEquals(defaultTargetVersion, returnCallingTargetVersion()) + assertEquals(defaultTargetVersion, CordappInfoResolver.currentTargetVersion) } - @Test() - fun `When more than one cordapp is registered for the same class, the resolver returns null`() { + @Test + fun `when more than one cordapp is registered for the same class, the resolver returns null`() { CordappInfoResolver.register(listOf(javaClass.name), CordappImpl.Info("test", "test", "2", 3, 222)) CordappInfoResolver.register(listOf(javaClass.name), CordappImpl.Info("test1", "test1", "1", 2, 456)) - assertEquals(0, returnCallingTargetVersion()) + assertThat(CordappInfoResolver.currentCordappInfo).isNull() } - - private fun returnCallingTargetVersion(): Int { - return CordappInfoResolver.getCorDappInfo()?.targetPlatformVersion ?: 0 - } -} \ No newline at end of file +} diff --git a/docs/source/api-flows.rst b/docs/source/api-flows.rst index 747e5276f9..65af0dcde9 100644 --- a/docs/source/api-flows.rst +++ b/docs/source/api-flows.rst @@ -450,6 +450,9 @@ An example is the ``@InitiatingFlow InitiatorFlow``/``@InitiatedBy ResponderFlow .. note:: Initiating flows are versioned separately from their parents. +.. note:: The only exception to this rule is ``FinalityFlow`` which is annotated with ``@InitiatingFlow`` but is an inlined flow. This flow + was previously initiating and the annotation exists to maintain backwards compatibility with old code. + Core initiating subflows ~~~~~~~~~~~~~~~~~~~~~~~~ Corda-provided initiating subflows are a little different to standard ones as they are versioned together with the @@ -460,8 +463,6 @@ Library flows ^^^^^^^^^^^^^ Corda installs four initiating subflow pairs on each node by default: -* ``FinalityFlow``/``FinalityHandler``, which should be used to notarise and record a transaction and broadcast it to - all relevant parties * ``NotaryChangeFlow``/``NotaryChangeHandler``, which should be used to change a state's notary * ``ContractUpgradeFlow.Initiate``/``ContractUpgradeHandler``, which should be used to change a state's contract * ``SwapIdentitiesFlow``/``SwapIdentitiesHandler``, which is used to exchange confidential identities with a @@ -474,10 +475,13 @@ Corda installs four initiating subflow pairs on each node by default: Corda also provides a number of built-in inlined subflows that should be used for handling common tasks. The most important are: -* ``CollectSignaturesFlow`` (inlined), which should be used to collect a transaction's required signatures -* ``SendTransactionFlow`` (inlined), which should be used to send a signed transaction if it needed to be resolved on +* ``FinalityFlow`` which is used to notarise, record locally and then broadcast a signed transaction to its participants + and any extra parties. +* ``ReceiveFinalityFlow`` to receive these notarised transactions from the ``FinalityFlow`` sender and record locally. +* ``CollectSignaturesFlow`` , which should be used to collect a transaction's required signatures +* ``SendTransactionFlow`` , which should be used to send a signed transaction if it needed to be resolved on the other side. -* ``ReceiveTransactionFlow`` (inlined), which should be used receive a signed transaction +* ``ReceiveTransactionFlow``, which should be used receive a signed transaction Let's look at some of these flows in more detail. @@ -516,20 +520,26 @@ We can also choose to send the transaction to additional parties who aren't one :end-before: DOCEND 10 :dedent: 12 -Only one party has to call ``FinalityFlow`` for a given transaction to be recorded by all participants. It does -**not** need to be called by each participant individually. +Only one party has to call ``FinalityFlow`` for a given transaction to be recorded by all participants. It **must not** +be called by every participant. Instead, every other particpant **must** call ``ReceiveFinalityFlow`` in their responder +flow to receive the transaction: -Because the transaction has already been notarised and the input states consumed, if the participants when receiving the -transaction fail to verify it, or the receiving flow (the finality handler) fails due to some other error, we then have -the scenario where not all parties have the correct up to date view of the ledger. To recover from this the finality handler -is automatically sent to the flow hospital where it's suspended and retried from its last checkpoint on node restart. -This gives the node operator the opportunity to recover from the error. Until the issue is resolved the node will continue -to retry the flow on each startup. +.. container:: codeset -.. note:: It's possible to forcibly terminate the erroring finality handler using the ``killFlow`` RPC but at the risk - of an inconsistent view of the ledger. + .. literalinclude:: ../../docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/FlowCookbook.kt + :language: kotlin + :start-after: DOCSTART ReceiveFinalityFlow + :end-before: DOCEND ReceiveFinalityFlow + :dedent: 8 -.. note:: A future release will allow retrying hospitalised flows without restarting the node, i.e. via RPC. + .. literalinclude:: ../../docs/source/example-code/src/main/java/net/corda/docs/java/FlowCookbook.java + :language: java + :start-after: DOCSTART ReceiveFinalityFlow + :end-before: DOCEND ReceiveFinalityFlow + :dedent: 12 + +``idOfTxWeSigned`` is an optional parameter used to confirm that we got the right transaction. It comes from using ``SignTransactionFlow`` +which is described below. CollectSignaturesFlow/SignTransactionFlow ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/source/api-persistence.rst b/docs/source/api-persistence.rst index abe2d2b5e2..f1ca9ef1df 100644 --- a/docs/source/api-persistence.rst +++ b/docs/source/api-persistence.rst @@ -136,23 +136,23 @@ Use the ``ServiceHub`` ``jdbcSession`` function to obtain a JDBC connection as i :start-after: DOCSTART JdbcSession :end-before: DOCEND JdbcSession -JDBC sessions can be used in Flows and Service Plugins (see ":doc:`flow-state-machines`") +JDBC sessions can be used in flows and services (see ":doc:`flow-state-machines`"). -The following example illustrates the creation of a custom corda service using a jdbcSession: +The following example illustrates the creation of a custom Corda service using a ``jdbcSession``: -.. literalinclude:: ../../docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/CustomVaultQuery.kt +.. literalinclude:: ../../docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/vault/CustomVaultQuery.kt :language: kotlin :start-after: DOCSTART CustomVaultQuery :end-before: DOCEND CustomVaultQuery which is then referenced within a custom flow: -.. literalinclude:: ../../docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/CustomVaultQuery.kt +.. literalinclude:: ../../docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/vault/CustomVaultQuery.kt :language: kotlin :start-after: DOCSTART TopupIssuer :end-before: DOCEND TopupIssuer -For examples on testing ``@CordaService`` implementations, see the oracle example :doc:`here ` +For examples on testing ``@CordaService`` implementations, see the oracle example :doc:`here `. JPA Support ----------- diff --git a/docs/source/api-states.rst b/docs/source/api-states.rst index 6b9e6ed0ef..d49a9a00a7 100644 --- a/docs/source/api-states.rst +++ b/docs/source/api-states.rst @@ -24,7 +24,7 @@ are considered to have a stake in the state. Among other things, the ``participa * Need to sign any notary-change and contract-upgrade transactions involving this state -* Receive any finalised transactions involving this state as part of ``FinalityFlow`` +* Receive any finalised transactions involving this state as part of ``FinalityFlow`` / ``ReceiveFinalityFlow`` ContractState sub-interfaces ---------------------------- diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 08628d9da3..5080f61a1a 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -12,9 +12,21 @@ Unreleased * New "validate-configuration" sub-command to `corda.jar`, allowing to validate the actual node configuration without starting the node. -* Introduced new optional network bootstrapper command line option (--minimum-platform-version) to set as a network parameter +* CorDapps now have the ability to specify a minimum platform version in their MANIFEST.MF to prevent old nodes from loading them. -* Introduce minimum and target platform version for CorDapps. +* CorDapps have the ability to specify a target platform version in their MANIFEST.MF as a means of indicating to the node + the app was designed and tested on that version. + +* Nodes will no longer automatically reject flow initiation requests for flows they don't know about. Instead the request will remain + un-acknowledged in the message broker. This enables the recovery scenerio whereby any missing CorDapp can be installed and retried on node + restart. As a consequence the initiating flow will be blocked until the receiving node has resolved the issue. + +* ``FinalityFlow`` is now an inlined flow and no longer requires a handler flow in the counterparty. This is to fix the + security problem with the handler flow as it accepts any transaction it receives without any checks. Existing CorDapp + binaries relying on this old behaviour will continue to function as previously. However, it is strongly recommended that + CorDapps switch to this new API. See :doc:`upgrade-notes` for further details. + +* Introduced new optional network bootstrapper command line option (--minimum-platform-version) to set as a network parameter * BFT-Smart and Raft notary implementations have been extracted out of node into ``experimental`` CorDapps to emphasise their experimental nature. Moreover, the BFT-Smart notary will only work in dev mode due to its use of Java serialization. diff --git a/docs/source/contributing-flow-state-machines.rst b/docs/source/contributing-flow-state-machines.rst index c1736288a5..5f88aace8a 100644 --- a/docs/source/contributing-flow-state-machines.rst +++ b/docs/source/contributing-flow-state-machines.rst @@ -85,12 +85,12 @@ flow with a full node. .. container:: codeset - .. literalinclude:: ../../docs/source/example-code/src/integration-test/kotlin/net/corda/docs/TutorialFlowAsyncOperationTest.kt + .. literalinclude:: ../../docs/source/example-code/src/integration-test/kotlin/net/corda/docs/kotlin/tutorial/test/TutorialFlowAsyncOperationTest.kt :language: kotlin :start-after: DOCSTART summingWorks :end-before: DOCEND summingWorks - .. literalinclude:: ../../docs/source/example-code/src/integration-test/java/net/corda/docs/java/TutorialFlowAsyncOperationTest.java + .. literalinclude:: ../../docs/source/example-code/src/integration-test/java/net/corda/docs/java/tutorial/test/TutorialFlowAsyncOperationTest.java :language: java :start-after: DOCSTART summingWorks :end-before: DOCEND summingWorks diff --git a/docs/source/example-code/src/integration-test/java/net/corda/docs/JavaIntegrationTestingTutorial.java b/docs/source/example-code/src/integration-test/java/net/corda/docs/java/tutorial/test/JavaIntegrationTestingTutorial.java similarity index 96% rename from docs/source/example-code/src/integration-test/java/net/corda/docs/JavaIntegrationTestingTutorial.java rename to docs/source/example-code/src/integration-test/java/net/corda/docs/java/tutorial/test/JavaIntegrationTestingTutorial.java index 92c696e592..c19b143499 100644 --- a/docs/source/example-code/src/integration-test/java/net/corda/docs/JavaIntegrationTestingTutorial.java +++ b/docs/source/example-code/src/integration-test/java/net/corda/docs/java/tutorial/test/JavaIntegrationTestingTutorial.java @@ -1,4 +1,4 @@ -package net.corda.docs; +package net.corda.docs.java.tutorial.test; import net.corda.client.rpc.CordaRPCClient; import net.corda.core.concurrent.CordaFuture; @@ -22,7 +22,9 @@ import org.junit.ClassRule; import org.junit.Test; import rx.Observable; -import java.util.*; +import java.util.Currency; +import java.util.HashSet; +import java.util.List; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; @@ -48,7 +50,7 @@ public class JavaIntegrationTestingTutorial extends IntegrationTest { // START 1 driver(new DriverParameters() .withStartNodesInProcess(true) - .withExtraCordappPackagesToScan(Arrays.asList("net.corda.finance.contracts.asset", "net.corda.finance.schemas")), dsl -> { + .withExtraCordappPackagesToScan(singletonList("net.corda.finance")), dsl -> { User aliceUser = new User("aliceUser", "testPassword1", new HashSet<>(asList( startFlow(CashIssueAndPaymentFlow.class), diff --git a/docs/source/example-code/src/integration-test/java/net/corda/docs/java/TutorialFlowAsyncOperationTest.java b/docs/source/example-code/src/integration-test/java/net/corda/docs/java/tutorial/test/TutorialFlowAsyncOperationTest.java similarity index 98% rename from docs/source/example-code/src/integration-test/java/net/corda/docs/java/TutorialFlowAsyncOperationTest.java rename to docs/source/example-code/src/integration-test/java/net/corda/docs/java/tutorial/test/TutorialFlowAsyncOperationTest.java index be94b19888..ad7128fd4f 100644 --- a/docs/source/example-code/src/integration-test/java/net/corda/docs/java/TutorialFlowAsyncOperationTest.java +++ b/docs/source/example-code/src/integration-test/java/net/corda/docs/java/tutorial/test/TutorialFlowAsyncOperationTest.java @@ -1,4 +1,4 @@ -package net.corda.docs.java; +package net.corda.docs.java.tutorial.test; import kotlin.Unit; import net.corda.client.rpc.CordaRPCClient; diff --git a/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/IntegrationTestingTutorial.kt b/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/IntegrationTestingTutorial.kt deleted file mode 100644 index 24a5e9ce1f..0000000000 --- a/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/IntegrationTestingTutorial.kt +++ /dev/null @@ -1,152 +0,0 @@ -package net.corda.docs - -import net.corda.client.rpc.CordaRPCClient -import net.corda.core.internal.concurrent.transpose -import net.corda.core.messaging.CordaRPCOps -import net.corda.core.messaging.startFlow -import net.corda.core.messaging.vaultTrackBy -import net.corda.core.node.services.Vault -import net.corda.core.node.services.vault.QueryCriteria -import net.corda.core.utilities.OpaqueBytes -import net.corda.core.utilities.getOrThrow -import net.corda.finance.DOLLARS -import net.corda.finance.contracts.asset.Cash -import net.corda.finance.flows.CashIssueFlow -import net.corda.finance.flows.CashPaymentFlow -import net.corda.node.services.Permissions.Companion.invokeRpc -import net.corda.node.services.Permissions.Companion.startFlow -import net.corda.testing.core.* -import net.corda.testing.driver.DriverParameters -import net.corda.testing.driver.driver -import net.corda.testing.internal.IntegrationTest -import net.corda.testing.internal.IntegrationTestSchemas -import net.corda.testing.internal.toDatabaseSchemaName -import net.corda.testing.node.User -import org.junit.ClassRule -import org.junit.Test -import kotlin.test.assertEquals - -class IntegrationTestingTutorial : IntegrationTest() { - companion object { - @ClassRule - @JvmField - val databaseSchemas = IntegrationTestSchemas(ALICE_NAME.toDatabaseSchemaName(), BOB_NAME.toDatabaseSchemaName(), - DUMMY_NOTARY_NAME.toDatabaseSchemaName()) - } - - @Test - fun `alice bob cash exchange example`() { - // START 1 - driver(DriverParameters( - startNodesInProcess = true, - extraCordappPackagesToScan = listOf("net.corda.finance.contracts.asset","net.corda.finance.schemas") - )) { - val aliceUser = User("aliceUser", "testPassword1", permissions = setOf( - startFlow(), - startFlow(), - invokeRpc("vaultTrackBy"), - invokeRpc(CordaRPCOps::notaryIdentities), - invokeRpc(CordaRPCOps::networkMapFeed) - )) - val bobUser = User("bobUser", "testPassword2", permissions = setOf( - startFlow(), - invokeRpc("vaultTrackBy"), - invokeRpc(CordaRPCOps::networkMapFeed) - )) - val (alice, bob) = listOf( - startNode(providedName = ALICE_NAME, rpcUsers = listOf(aliceUser)), - startNode(providedName = BOB_NAME, rpcUsers = listOf(bobUser)) - ).transpose().getOrThrow() - - // END 1 - - // START 2 - val aliceClient = CordaRPCClient(alice.rpcAddress) - val aliceProxy = aliceClient.start("aliceUser", "testPassword1").proxy - - val bobClient = CordaRPCClient(bob.rpcAddress) - val bobProxy = bobClient.start("bobUser", "testPassword2").proxy - // END 2 - - // START 3 - val bobVaultUpdates = bobProxy.vaultTrackBy(criteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.ALL)).updates - val aliceVaultUpdates = aliceProxy.vaultTrackBy(criteria = QueryCriteria.VaultQueryCriteria(status = Vault.StateStatus.ALL)).updates - // END 3 - - // START 4 - val numberOfStates = 10 - val issueRef = OpaqueBytes.of(0) - val notaryParty = aliceProxy.notaryIdentities().first() - (1..numberOfStates).map { i -> - aliceProxy.startFlow(::CashIssueFlow, - i.DOLLARS, - issueRef, - notaryParty - ).returnValue - }.transpose().getOrThrow() - // We wait for all of the issuances to run before we start making payments - (1..numberOfStates).map { i -> - aliceProxy.startFlow(::CashPaymentFlow, - i.DOLLARS, - bob.nodeInfo.singleIdentity(), - true - ).returnValue - }.transpose().getOrThrow() - - bobVaultUpdates.expectEvents { - parallel( - (1..numberOfStates).map { i -> - expect( - match = { update: Vault.Update -> - update.produced.first().state.data.amount.quantity == i * 100L - } - ) { update -> - println("Bob vault update of $update") - } - } - ) - } - // END 4 - - // START 5 - for (i in 1..numberOfStates) { - bobProxy.startFlow(::CashPaymentFlow, i.DOLLARS, alice.nodeInfo.singleIdentity()).returnValue.getOrThrow() - } - - aliceVaultUpdates.expectEvents { - sequence( - // issuance - parallel( - (1..numberOfStates).map { i -> - expect(match = { it.moved() == -i * 100 }) { update: Vault.Update -> - assertEquals(0, update.consumed.size) - } - } - ), - // move to Bob - parallel( - (1..numberOfStates).map { i -> - expect(match = { it.moved() == i * 100 }) { _: Vault.Update -> - } - } - ), - // move back to Alice - sequence( - (1..numberOfStates).map { i -> - expect(match = { it.moved() == -i * 100 }) { update: Vault.Update -> - assertEquals(update.consumed.size, 0) - } - } - ) - ) - } - // END 5 - } - } - - private fun Vault.Update.moved(): Int { - val consumedSum = consumed.sumBy { it.state.data.amount.quantity.toInt() } - val producedSum = produced.sumBy { it.state.data.amount.quantity.toInt() } - return consumedSum - producedSum - } -} \ No newline at end of file diff --git a/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/KotlinIntegrationTestingTutorial.kt b/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/kotlin/tutorial/test/KotlinIntegrationTestingTutorial.kt similarity index 94% rename from docs/source/example-code/src/integration-test/kotlin/net/corda/docs/KotlinIntegrationTestingTutorial.kt rename to docs/source/example-code/src/integration-test/kotlin/net/corda/docs/kotlin/tutorial/test/KotlinIntegrationTestingTutorial.kt index 40394bf355..ccbf03bbab 100644 --- a/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/KotlinIntegrationTestingTutorial.kt +++ b/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/kotlin/tutorial/test/KotlinIntegrationTestingTutorial.kt @@ -1,4 +1,4 @@ -package net.corda.docs +package net.corda.docs.kotlin.tutorial.test import net.corda.client.rpc.CordaRPCClient import net.corda.core.contracts.Amount @@ -40,10 +40,7 @@ class KotlinIntegrationTestingTutorial : IntegrationTest() { @Test fun `alice bob cash exchange example`() { // START 1 - driver(DriverParameters( - startNodesInProcess = true, - extraCordappPackagesToScan = listOf("net.corda.finance.contracts.asset", "net.corda.finance.schemas") - )) { + driver(DriverParameters(startNodesInProcess = true, extraCordappPackagesToScan = listOf("net.corda.finance"))) { val aliceUser = User("aliceUser", "testPassword1", permissions = setOf( startFlow(), invokeRpc("vaultTrackBy") diff --git a/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/TutorialFlowAsyncOperationTest.kt b/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/kotlin/tutorial/test/TutorialFlowAsyncOperationTest.kt similarity index 97% rename from docs/source/example-code/src/integration-test/kotlin/net/corda/docs/TutorialFlowAsyncOperationTest.kt rename to docs/source/example-code/src/integration-test/kotlin/net/corda/docs/kotlin/tutorial/test/TutorialFlowAsyncOperationTest.kt index 5d9720f4d8..73f4dbe193 100644 --- a/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/TutorialFlowAsyncOperationTest.kt +++ b/docs/source/example-code/src/integration-test/kotlin/net/corda/docs/kotlin/tutorial/test/TutorialFlowAsyncOperationTest.kt @@ -1,4 +1,4 @@ -package net.corda.docs +package net.corda.docs.kotlin.tutorial.test import net.corda.client.rpc.CordaRPCClient import net.corda.core.messaging.startFlow diff --git a/docs/source/example-code/src/main/java/net/corda/docs/java/FinalityFlowMigration.java b/docs/source/example-code/src/main/java/net/corda/docs/java/FinalityFlowMigration.java new file mode 100644 index 0000000000..ddb38ebd0b --- /dev/null +++ b/docs/source/example-code/src/main/java/net/corda/docs/java/FinalityFlowMigration.java @@ -0,0 +1,134 @@ +package net.corda.docs.java; + +import co.paralleluniverse.fibers.Suspendable; +import net.corda.core.flows.*; +import net.corda.core.identity.Party; +import net.corda.core.transactions.SignedTransaction; +import org.jetbrains.annotations.NotNull; + +import static java.util.Collections.singletonList; + +@SuppressWarnings("ALL") +public class FinalityFlowMigration { + public static SignedTransaction dummyTransactionWithParticipant(Party party) { + throw new UnsupportedOperationException(); + } + + // DOCSTART SimpleFlowUsingOldApi + public static class SimpleFlowUsingOldApi extends FlowLogic { + private final Party counterparty; + + @Suspendable + @Override + public SignedTransaction call() throws FlowException { + SignedTransaction stx = dummyTransactionWithParticipant(counterparty); + return subFlow(new FinalityFlow(stx)); + } + // DOCEND SimpleFlowUsingOldApi + + public SimpleFlowUsingOldApi(Party counterparty) { + this.counterparty = counterparty; + } + } + + // DOCSTART SimpleFlowUsingNewApi + // Notice how the flow *must* now be an initiating flow even when it wasn't before. + @InitiatingFlow + public static class SimpleFlowUsingNewApi extends FlowLogic { + private final Party counterparty; + + @Suspendable + @Override + public SignedTransaction call() throws FlowException { + SignedTransaction stx = dummyTransactionWithParticipant(counterparty); + // For each non-local participant in the transaction we must initiate a flow session with them. + FlowSession session = initiateFlow(counterparty); + return subFlow(new FinalityFlow(stx, session)); + } + // DOCEND SimpleFlowUsingNewApi + + public SimpleFlowUsingNewApi(Party counterparty) { + this.counterparty = counterparty; + } + } + // DOCSTART SimpleNewResponderFlow + // All participants will run this flow to receive and record the finalised transaction into their vault. + @InitiatedBy(SimpleFlowUsingNewApi.class) + public static class SimpleNewResponderFlow extends FlowLogic { + private final FlowSession otherSide; + + @Suspendable + @Override + public Void call() throws FlowException { + subFlow(new ReceiveFinalityFlow(otherSide)); + return null; + } + // DOCEND SimpleNewResponderFlow + + public SimpleNewResponderFlow(FlowSession otherSide) { + this.otherSide = otherSide; + } + } + + // DOCSTART ExistingInitiatingFlow + // Assuming the previous version of the flow was 1 (the default if none is specified), we increment the version number to 2 + // to allow for backwards compatibility with nodes running the old CorDapp. + @InitiatingFlow(version = 2) + public static class ExistingInitiatingFlow extends FlowLogic { + private final Party counterparty; + + @Suspendable + @Override + public SignedTransaction call() throws FlowException { + SignedTransaction partiallySignedTx = dummyTransactionWithParticipant(counterparty); + FlowSession session = initiateFlow(counterparty); + SignedTransaction fullySignedTx = subFlow(new CollectSignaturesFlow(partiallySignedTx, singletonList(session))); + // Determine which version of the flow that other side is using. + if (session.getCounterpartyFlowInfo().getFlowVersion() == 1) { + // Use the old API if the other side is using the previous version of the flow. + return subFlow(new FinalityFlow(fullySignedTx)); + } else { + // Otherwise they're at least on version 2 and so we can send the finalised transaction on the existing session. + return subFlow(new FinalityFlow(fullySignedTx, session)); + } + } + // DOCEND ExistingInitiatingFlow + + public ExistingInitiatingFlow(Party counterparty) { + this.counterparty = counterparty; + } + } + + @InitiatedBy(ExistingInitiatingFlow.class) + public static class ExistingResponderFlow extends FlowLogic { + private final FlowSession otherSide; + + public ExistingResponderFlow(FlowSession otherSide) { + this.otherSide = otherSide; + } + + @Suspendable + @Override + public Void call() throws FlowException { + SignedTransaction txWeJustSigned = subFlow(new SignTransactionFlow(otherSide) { + @Suspendable + @Override + protected void checkTransaction(@NotNull SignedTransaction stx) throws FlowException { + // Do checks here + } + }); + // DOCSTART ExistingResponderFlow + if (otherSide.getCounterpartyFlowInfo().getFlowVersion() >= 2) { + // The other side is not using the old CorDapp so call ReceiveFinalityFlow to record the finalised transaction. + // If SignTransactionFlow is used then we can verify the tranaction we receive for recording is the same one + // that was just signed. + subFlow(new ReceiveFinalityFlow(otherSide, txWeJustSigned.getId())); + } else { + // Otherwise the other side is running the old CorDapp and so we don't need to do anything further. The node + // will automatically record the finalised transaction using the old insecure mechanism. + } + // DOCEND ExistingResponderFlow + return null; + } + } +} diff --git a/docs/source/example-code/src/main/java/net/corda/docs/java/FlowCookbook.java b/docs/source/example-code/src/main/java/net/corda/docs/java/FlowCookbook.java index af0960ab2a..2ee468fdbc 100644 --- a/docs/source/example-code/src/main/java/net/corda/docs/java/FlowCookbook.java +++ b/docs/source/example-code/src/main/java/net/corda/docs/java/FlowCookbook.java @@ -28,6 +28,7 @@ import java.security.GeneralSecurityException; import java.security.PublicKey; import java.time.Duration; import java.time.Instant; +import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Set; @@ -579,13 +580,13 @@ public class FlowCookbook { // We notarise the transaction and get it recorded in the vault of // the participants of all the transaction's states. // DOCSTART 09 - SignedTransaction notarisedTx1 = subFlow(new FinalityFlow(fullySignedTx, FINALISATION.childProgressTracker())); + SignedTransaction notarisedTx1 = subFlow(new FinalityFlow(fullySignedTx, singleton(counterpartySession), FINALISATION.childProgressTracker())); // DOCEND 09 // We can also choose to send it to additional parties who aren't one // of the state's participants. // DOCSTART 10 - Set additionalParties = singleton(regulator); - SignedTransaction notarisedTx2 = subFlow(new FinalityFlow(fullySignedTx, additionalParties, FINALISATION.childProgressTracker())); + List partySessions = Arrays.asList(counterpartySession, initiateFlow(regulator)); + SignedTransaction notarisedTx2 = subFlow(new FinalityFlow(fullySignedTx, partySessions, FINALISATION.childProgressTracker())); // DOCEND 10 return null; @@ -667,7 +668,7 @@ public class FlowCookbook { } } - subFlow(new SignTxFlow(counterpartySession, SignTransactionFlow.tracker())); + SecureHash idOfTxWeSigned = subFlow(new SignTxFlow(counterpartySession, SignTransactionFlow.tracker())).getId(); // DOCEND 16 /*------------------------------ @@ -675,9 +676,12 @@ public class FlowCookbook { ------------------------------*/ progressTracker.setCurrentStep(FINALISATION); - // Nothing to do here! As long as some other party calls - // ``FinalityFlow``, the recording of the transaction on our node - // we be handled automatically. + // As the final step the responder waits to receive the notarised transaction from the sending party + // Since it knows the ID of the transaction it just signed, the transaction ID is specified to ensure the correct + // transaction is received and recorded. + // DOCSTART ReceiveFinalityFlow + subFlow(new ReceiveFinalityFlow(counterpartySession, idOfTxWeSigned)); + // DOCEND ReceiveFinalityFlow return null; } diff --git a/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/helloworld/IOUFlow.java b/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/helloworld/IOUFlow.java index cadcae2ce2..e077de4878 100644 --- a/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/helloworld/IOUFlow.java +++ b/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/helloworld/IOUFlow.java @@ -2,16 +2,12 @@ package net.corda.docs.java.tutorial.helloworld; import co.paralleluniverse.fibers.Suspendable; import com.template.TemplateContract; -import net.corda.core.flows.FlowException; -import net.corda.core.flows.FlowLogic; -import net.corda.core.flows.InitiatingFlow; -import net.corda.core.flows.StartableByRPC; +import net.corda.core.flows.*; import net.corda.core.utilities.ProgressTracker; // DOCSTART 01 // Add these imports: import net.corda.core.contracts.Command; -import net.corda.core.flows.FinalityFlow; import net.corda.core.identity.Party; import net.corda.core.transactions.SignedTransaction; import net.corda.core.transactions.TransactionBuilder; @@ -59,8 +55,11 @@ public class IOUFlow extends FlowLogic { // Signing the transaction. SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder); - // Finalising the transaction. - subFlow(new FinalityFlow(signedTx)); + // Creating a session with the other party. + FlowSession otherPartySession = initiateFlow(otherParty); + + // We finalise the transaction and then send it to the counterparty. + subFlow(new FinalityFlow(signedTx, otherPartySession)); return null; } diff --git a/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/helloworld/IOUFlowResponder.java b/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/helloworld/IOUFlowResponder.java new file mode 100644 index 0000000000..b4343808c0 --- /dev/null +++ b/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/helloworld/IOUFlowResponder.java @@ -0,0 +1,25 @@ +package net.corda.docs.java.tutorial.helloworld; + +import co.paralleluniverse.fibers.Suspendable; +import net.corda.core.flows.*; + +@SuppressWarnings("unused") +// DOCSTART 01 +// Replace Responder's definition with: +@InitiatedBy(IOUFlow.class) +public class IOUFlowResponder extends FlowLogic { + private final FlowSession otherPartySession; + + public IOUFlowResponder(FlowSession otherPartySession) { + this.otherPartySession = otherPartySession; + } + + @Suspendable + @Override + public Void call() throws FlowException { + subFlow(new ReceiveFinalityFlow(otherPartySession)); + + return null; + } +} +// DOCEND 01 diff --git a/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/twoparty/IOUFlow.java b/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/twoparty/IOUFlow.java index 8f5221c641..f762bcdb4e 100644 --- a/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/twoparty/IOUFlow.java +++ b/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/twoparty/IOUFlow.java @@ -69,7 +69,7 @@ public class IOUFlow extends FlowLogic { signedTx, Arrays.asList(otherPartySession), CollectSignaturesFlow.tracker())); // Finalising the transaction. - subFlow(new FinalityFlow(fullySignedTx)); + subFlow(new FinalityFlow(fullySignedTx, otherPartySession)); return null; // DOCEND 02 diff --git a/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/twoparty/IOUFlowResponder.java b/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/twoparty/IOUFlowResponder.java index 35b2a3f97b..d210940891 100644 --- a/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/twoparty/IOUFlowResponder.java +++ b/docs/source/example-code/src/main/java/net/corda/docs/java/tutorial/twoparty/IOUFlowResponder.java @@ -1,15 +1,14 @@ package net.corda.docs.java.tutorial.twoparty; -// DOCSTART 01 -// Add these imports: import co.paralleluniverse.fibers.Suspendable; import net.corda.core.contracts.ContractState; +import net.corda.core.crypto.SecureHash; import net.corda.core.flows.*; import net.corda.core.transactions.SignedTransaction; -import net.corda.core.utilities.ProgressTracker; import static net.corda.core.contracts.ContractsDSL.requireThat; +@SuppressWarnings("unused") // Define IOUFlowResponder: @InitiatedBy(IOUFlow.class) public class IOUFlowResponder extends FlowLogic { @@ -22,9 +21,10 @@ public class IOUFlowResponder extends FlowLogic { @Suspendable @Override public Void call() throws FlowException { + // DOCSTART 01 class SignTxFlow extends SignTransactionFlow { - private SignTxFlow(FlowSession otherPartySession, ProgressTracker progressTracker) { - super(otherPartySession, progressTracker); + private SignTxFlow(FlowSession otherPartySession) { + super(otherPartySession); } @Override @@ -39,9 +39,11 @@ public class IOUFlowResponder extends FlowLogic { } } - subFlow(new SignTxFlow(otherPartySession, SignTransactionFlow.Companion.tracker())); + SecureHash expectedTxId = subFlow(new SignTxFlow(otherPartySession)).getId(); + + subFlow(new ReceiveFinalityFlow(otherPartySession, expectedTxId)); return null; + // DOCEND 01 } } -// DOCEND 01 \ No newline at end of file diff --git a/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/FinalityFlowMigration.kt b/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/FinalityFlowMigration.kt new file mode 100644 index 0000000000..493105a875 --- /dev/null +++ b/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/FinalityFlowMigration.kt @@ -0,0 +1,91 @@ +@file:Suppress("DEPRECATION", "unused", "UNUSED_PARAMETER") + +package net.corda.docs.kotlin + +import co.paralleluniverse.fibers.Suspendable +import net.corda.core.flows.* +import net.corda.core.identity.Party +import net.corda.core.transactions.SignedTransaction + +private fun dummyTransactionWithParticipant(party: Party): SignedTransaction = TODO() + +// DOCSTART SimpleFlowUsingOldApi +class SimpleFlowUsingOldApi(private val counterparty: Party) : FlowLogic() { + @Suspendable + override fun call(): SignedTransaction { + val stx = dummyTransactionWithParticipant(counterparty) + return subFlow(FinalityFlow(stx)) + } +} +// DOCEND SimpleFlowUsingOldApi + +// DOCSTART SimpleFlowUsingNewApi +// Notice how the flow *must* now be an initiating flow even when it wasn't before. +@InitiatingFlow +class SimpleFlowUsingNewApi(private val counterparty: Party) : FlowLogic() { + @Suspendable + override fun call(): SignedTransaction { + val stx = dummyTransactionWithParticipant(counterparty) + // For each non-local participant in the transaction we must initiate a flow session with them. + val session = initiateFlow(counterparty) + return subFlow(FinalityFlow(stx, session)) + } +} +// DOCEND SimpleFlowUsingNewApi + +// DOCSTART SimpleNewResponderFlow +// All participants will run this flow to receive and record the finalised transaction into their vault. +@InitiatedBy(SimpleFlowUsingNewApi::class) +class SimpleNewResponderFlow(private val otherSide: FlowSession) : FlowLogic() { + @Suspendable + override fun call() { + subFlow(ReceiveFinalityFlow(otherSide)) + } +} +// DOCEND SimpleNewResponderFlow + +// DOCSTART ExistingInitiatingFlow +// Assuming the previous version of the flow was 1 (the default if none is specified), we increment the version number to 2 +// to allow for backwards compatibility with nodes running the old CorDapp. +@InitiatingFlow(version = 2) +class ExistingInitiatingFlow(private val counterparty: Party) : FlowLogic() { + @Suspendable + override fun call(): SignedTransaction { + val partiallySignedTx = dummyTransactionWithParticipant(counterparty) + val session = initiateFlow(counterparty) + val fullySignedTx = subFlow(CollectSignaturesFlow(partiallySignedTx, listOf(session))) + // Determine which version of the flow that other side is using. + return if (session.getCounterpartyFlowInfo().flowVersion == 1) { + // Use the old API if the other side is using the previous version of the flow. + subFlow(FinalityFlow(fullySignedTx)) + } else { + // Otherwise they're at least on version 2 and so we can send the finalised transaction on the existing session. + subFlow(FinalityFlow(fullySignedTx, session)) + } + } +} +// DOCEND ExistingInitiatingFlow + +@InitiatedBy(ExistingInitiatingFlow::class) +class ExistingResponderFlow(private val otherSide: FlowSession) : FlowLogic() { + @Suspendable + override fun call() { + val txWeJustSigned = subFlow(object : SignTransactionFlow(otherSide) { + @Suspendable + override fun checkTransaction(stx: SignedTransaction) { + // Do checks here + } + }) + // DOCSTART ExistingResponderFlow + if (otherSide.getCounterpartyFlowInfo().flowVersion >= 2) { + // The other side is not using the old CorDapp so call ReceiveFinalityFlow to record the finalised transaction. + // If SignTransactionFlow is used then we can verify the tranaction we receive for recording is the same one + // that was just signed. + subFlow(ReceiveFinalityFlow(otherSide, expectedTxId = txWeJustSigned.id)) + } else { + // Otherwise the other side is running the old CorDapp and so we don't need to do anything further. The node + // will automatically record the finalised transaction using the old insecure mechanism. + } + // DOCEND ExistingResponderFlow + } +} diff --git a/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/FlowCookbook.kt b/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/FlowCookbook.kt index 950f813d07..6133689539 100644 --- a/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/FlowCookbook.kt +++ b/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/FlowCookbook.kt @@ -568,13 +568,13 @@ class InitiatorFlow(val arg1: Boolean, val arg2: Int, private val counterparty: // We notarise the transaction and get it recorded in the vault of // the participants of all the transaction's states. // DOCSTART 09 - val notarisedTx1: SignedTransaction = subFlow(FinalityFlow(fullySignedTx, FINALISATION.childProgressTracker())) + val notarisedTx1: SignedTransaction = subFlow(FinalityFlow(fullySignedTx, listOf(counterpartySession), FINALISATION.childProgressTracker())) // DOCEND 09 // We can also choose to send it to additional parties who aren't one // of the state's participants. // DOCSTART 10 - val additionalParties: Set = setOf(regulator) - val notarisedTx2: SignedTransaction = subFlow(FinalityFlow(fullySignedTx, additionalParties, FINALISATION.childProgressTracker())) + val partySessions: List = listOf(counterpartySession, initiateFlow(regulator)) + val notarisedTx2: SignedTransaction = subFlow(FinalityFlow(fullySignedTx, partySessions, FINALISATION.childProgressTracker())) // DOCEND 10 } } @@ -643,7 +643,7 @@ class ResponderFlow(val counterpartySession: FlowSession) : FlowLogic() { } } - subFlow(signTransactionFlow) + val idOfTxWeSigned = subFlow(signTransactionFlow).id // DOCEND 16 /**----------------------------- @@ -651,8 +651,11 @@ class ResponderFlow(val counterpartySession: FlowSession) : FlowLogic() { -----------------------------**/ progressTracker.currentStep = FINALISATION - // Nothing to do here! As long as some other party calls - // ``FinalityFlow``, the recording of the transaction on our node - // we be handled automatically. + // As the final step the responder waits to receive the notarised transaction from the sending party + // Since it knows the ID of the transaction it just signed, the transaction ID is specified to ensure the correct + // transaction is received and recorded. + // DOCSTART ReceiveFinalityFlow + subFlow(ReceiveFinalityFlow(counterpartySession, expectedTxId = idOfTxWeSigned)) + // DOCEND ReceiveFinalityFlow } } diff --git a/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/FxTransactionBuildTutorial.kt b/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/FxTransactionBuildTutorial.kt index 052b4ddf21..1e84ad0f1f 100644 --- a/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/FxTransactionBuildTutorial.kt +++ b/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/FxTransactionBuildTutorial.kt @@ -160,7 +160,7 @@ class ForeignExchangeFlow(private val tradeId: String, } // Initiate the standard protocol to notarise and distribute to the involved parties. - subFlow(FinalityFlow(allPartySignedTx, setOf(counterparty))) + subFlow(FinalityFlow(allPartySignedTx, counterpartySession)) return allPartySignedTx.id } @@ -239,7 +239,8 @@ class ForeignExchangeRemoteFlow(private val source: FlowSession) : FlowLogic() { + @Suspendable + override fun call() { + subFlow(ReceiveFinalityFlow(otherPartySession)) + } +} +// DOCEND 01 diff --git a/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/tutorial/twoparty/IOUFlow.kt b/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/tutorial/twoparty/IOUFlow.kt index 6eb508b3f0..17c806d7d3 100644 --- a/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/tutorial/twoparty/IOUFlow.kt +++ b/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/tutorial/twoparty/IOUFlow.kt @@ -52,7 +52,7 @@ class IOUFlow(val iouValue: Int, val fullySignedTx = subFlow(CollectSignaturesFlow(signedTx, listOf(otherPartySession), CollectSignaturesFlow.tracker())) // Finalising the transaction. - subFlow(FinalityFlow(fullySignedTx)) + subFlow(FinalityFlow(fullySignedTx, otherPartySession)) // DOCEND 02 } } diff --git a/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/tutorial/twoparty/IOUFlowResponder.kt b/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/tutorial/twoparty/IOUFlowResponder.kt index 882d3061a5..7a87c3b351 100644 --- a/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/tutorial/twoparty/IOUFlowResponder.kt +++ b/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/tutorial/twoparty/IOUFlowResponder.kt @@ -17,7 +17,8 @@ import net.corda.core.transactions.SignedTransaction class IOUFlowResponder(val otherPartySession: FlowSession) : FlowLogic() { @Suspendable override fun call() { - val signTransactionFlow = object : SignTransactionFlow(otherPartySession, SignTransactionFlow.tracker()) { + // DOCSTART 01 + val signTransactionFlow = object : SignTransactionFlow(otherPartySession) { override fun checkTransaction(stx: SignedTransaction) = requireThat { val output = stx.tx.outputs.single().data "This must be an IOU transaction." using (output is IOUState) @@ -26,7 +27,9 @@ class IOUFlowResponder(val otherPartySession: FlowSession) : FlowLogic() { } } - subFlow(signTransactionFlow) + val expectedTxId = subFlow(signTransactionFlow).id + + subFlow(ReceiveFinalityFlow(otherPartySession, expectedTxId)) + // DOCEND 01 } } -// DOCEND 01 diff --git a/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/WorkflowTransactionBuildTutorial.kt b/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/txbuild/WorkflowTransactionBuildTutorial.kt similarity index 93% rename from docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/WorkflowTransactionBuildTutorial.kt rename to docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/txbuild/WorkflowTransactionBuildTutorial.kt index b2b34841f5..01829ddcc8 100644 --- a/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/WorkflowTransactionBuildTutorial.kt +++ b/docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/txbuild/WorkflowTransactionBuildTutorial.kt @@ -1,6 +1,6 @@ @file:Suppress("unused") -package net.corda.docs.kotlin +package net.corda.docs.kotlin.txbuild import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.* @@ -25,7 +25,7 @@ enum class WorkflowState { REJECTED } -const val TRADE_APPROVAL_PROGRAM_ID = "net.corda.docs.kotlin.TradeApprovalContract" +const val TRADE_APPROVAL_PROGRAM_ID = "net.corda.docs.kotlin.txbuild.TradeApprovalContract" /** * Minimal contract to encode a simple workflow with one initial state and two possible eventual states. @@ -93,6 +93,7 @@ data class TradeApprovalContract(val blank: Unit? = null) : Contract { * The protocol then sends a copy to the other node. We don't require the other party to sign * as their approval/rejection is to follow. */ +@InitiatingFlow class SubmitTradeApprovalFlow(private val tradeId: String, private val counterparty: Party) : FlowLogic>() { @Suspendable @@ -109,12 +110,20 @@ class SubmitTradeApprovalFlow(private val tradeId: String, // We can automatically sign as there is no untrusted data. val signedTx = serviceHub.signInitialTransaction(tx) // Notarise and distribute. - subFlow(FinalityFlow(signedTx, setOf(counterparty))) + subFlow(FinalityFlow(signedTx, initiateFlow(counterparty))) // Return the initial state return signedTx.tx.outRef(0) } } +@InitiatedBy(SubmitTradeApprovalFlow::class) +class SubmitTradeApprovalResponderFlow(private val otherSide: FlowSession) : FlowLogic() { + @Suspendable + override fun call() { + subFlow(ReceiveFinalityFlow(otherSide)) + } +} + /** * Simple flow to complete a proposal submitted by another party and ensure both nodes * end up with a fully signed copy of the state either as APPROVED, or REJECTED @@ -174,8 +183,8 @@ class SubmitCompletionFlow(private val ref: StateRef, private val verdict: Workf val selfSignedTx = serviceHub.signInitialTransaction(tx) //DOCEND 2 // Send the signed transaction to the originator and await their signature to confirm - val session = initiateFlow(newState.source) - val allPartySignedTx = session.sendAndReceive(selfSignedTx).unwrap { + val sourceSession = initiateFlow(newState.source) + val allPartySignedTx = sourceSession.sendAndReceive(selfSignedTx).unwrap { // Add their signature to our unmodified transaction. To check they signed the same tx. val agreedTx = selfSignedTx + it // Receive back their signature and confirm that it is for an unmodified transaction @@ -189,7 +198,7 @@ class SubmitCompletionFlow(private val ref: StateRef, private val verdict: Workf } // DOCSTART 4 // Notarise and distribute the completed transaction. - subFlow(FinalityFlow(allPartySignedTx, setOf(newState.source))) + subFlow(FinalityFlow(allPartySignedTx, sourceSession)) // DOCEND 4 // Return back the details of the completed state/transaction. return allPartySignedTx.tx.outRef(0) @@ -233,7 +242,7 @@ class RecordCompletionFlow(private val sourceSession: FlowSession) : FlowLogic) { @@ -86,7 +86,8 @@ class CustomVaultQueryTest { nodeA.info.singleIdentity(), OpaqueBytes.of(0x01), nodeA.info.singleIdentity(), - notary)).getOrThrow() + notary) + ).getOrThrow() } private fun getBalances(): Pair>, Map>> { diff --git a/docs/source/flow-state-machines.rst b/docs/source/flow-state-machines.rst index 63de6e6a25..a36b69f44c 100644 --- a/docs/source/flow-state-machines.rst +++ b/docs/source/flow-state-machines.rst @@ -227,8 +227,8 @@ Next, we call another subflow called ``SignTransactionFlow``. ``SignTransactionF The transaction then needs to be finalized. This is the the process of sending the transaction to a notary to assert (with another signature) that the time-window in the transaction (if any) is valid and there are no double spends. -In this flow, finalization is handled by the buyer, so we just wait for the signed transaction to appear in our -transaction storage. It will have the same ID as the one we started with but more signatures. +In this flow, finalization is handled by the buyer, we just wait for them to send it to us. It will have the same ID as +the one we started with but more signatures. Implementing the buyer ---------------------- @@ -314,9 +314,11 @@ On the buyer side, we use ``FinalityFlow`` to finalise the transaction. It will: * Record the transaction in the local vault, if it is relevant (i.e. involves the owner of the node). * Send the fully signed transaction to the other participants for recording as well. -.. warning:: If the seller stops before sending the finalised transaction to the buyer, the seller is left with a - valid transaction but the buyer isn't, so they can't spend the asset they just purchased! This sort of thing is not - always a risk (as the seller may not gain anything from that sort of behaviour except a lawsuit), but if it is, a future +On the seller side we use ``ReceiveFinalityFlow`` to receive and record the finalised transaction. + +.. warning:: If the buyer stops before sending the finalised transaction to the seller, the buyer is left with a + valid transaction but the seller isn't, so they don't get the cash! This sort of thing is not + always a risk (as the buyer may not gain anything from that sort of behaviour except a lawsuit), but if it is, a future version of the platform will allow you to ask the notary to send you the transaction as well, in case your counterparty does not. This is not the default because it reveals more private info to the notary. diff --git a/docs/source/hello-world-flow.rst b/docs/source/hello-world-flow.rst index b6281a51d4..51f5210076 100644 --- a/docs/source/hello-world-flow.rst +++ b/docs/source/hello-world-flow.rst @@ -21,11 +21,11 @@ require the following steps: 1. Building the transaction proposal for the issuance of a new IOU onto a ledger 2. Signing the transaction proposal - 3. Recording the transaction - 4. Sending the transaction to the IOU's borrower so that they can record it too + 3. Recording the transaction and sending it to the IOU's borrower so that they can record it too -At this stage, we do not require the borrower to approve and sign IOU issuance transactions. We will be able to impose -this requirement when we look at contracts in the next tutorial. +We also need the borrower to receive the transaction and record it for itself. At this stage, we do not require the borrower +to approve and sign IOU issuance transactions. We will be able to impose this requirement when we look at contracts in the +next tutorial. Subflows ^^^^^^^^ @@ -34,13 +34,11 @@ forcing each developer to reimplement their own logic to handle these tasks, Cor to handle these tasks. We call these flows that are invoked in the context of a larger flow to handle a repeatable task *subflows*. -In our case, we can automate steps 3 and 4 of the IOU issuance flow using ``FinalityFlow``. - FlowLogic --------- All flows must subclass ``FlowLogic``. You then define the steps taken by the flow by overriding ``FlowLogic.call``. -Let's define our ``IOUFlow``. Delete the existing ``Responder`` flow. Then replace the definition of ``Initiator`` with the following: +Let's define our ``IOUFlow``. Replace the definition of ``Initiator`` with the following: .. container:: codeset @@ -54,8 +52,9 @@ Let's define our ``IOUFlow``. Delete the existing ``Responder`` flow. Then repla :start-after: DOCSTART 01 :end-before: DOCEND 01 -If you're following along in Java, you'll also need to rename ``Initiator.java`` to ``IOUFlow.java``. Let's walk -through this code step-by-step. +If you're following along in Java, you'll also need to rename ``Initiator.java`` to ``IOUFlow.java``. + +Let's walk through this code step-by-step. We've defined our own ``FlowLogic`` subclass that overrides ``FlowLogic.call``. ``FlowLogic.call`` has a return type that must match the type parameter passed to ``FlowLogic`` - this is type returned by running the flow. @@ -73,7 +72,7 @@ annotation out will lead to some very weird error messages! There are also a few more annotations, on the ``FlowLogic`` subclass itself: * ``@InitiatingFlow`` means that this flow is part of a flow pair and that it triggers the other side to run the - the counterpart flow. + the counterpart flow (which in our case is the ``IOUFlowResponder`` defined below). * ``@StartableByRPC`` allows the node owner to start this flow via an RPC call Let's walk through the steps of ``FlowLogic.call`` itself. This is where we actually describe the procedure for @@ -145,15 +144,36 @@ We sign the transaction using ``ServiceHub.signInitialTransaction``, which retur Finalising the transaction ^^^^^^^^^^^^^^^^^^^^^^^^^^ -We now have a valid signed transaction. All that's left to do is to have it recorded by all the relevant parties. By -doing so, it will become a permanent part of the ledger. As discussed, we'll handle this process automatically using a -built-in flow called ``FinalityFlow``. ``FinalityFlow`` completely automates the process of: +We now have a valid signed transaction. All that's left to do is to get the notary to sign it, have that recorded +locally and then send it to all the relevant parties. Once that happens the transaction will become a permanent part of the +ledger. We use ``FinalityFlow`` which does all of this for the lender. -* Notarising the transaction if required (i.e. if the transaction contains inputs and/or a time-window) -* Recording it in our vault -* Sending it to the other participants (i.e. the lender) for them to record as well +For the borrower to receive the transaction they just need a flow that responds to the seller's. + +Creating the borrower's flow +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The borrower has to use ``ReceiveFinalityFlow`` in order to receive and record the transaction; it needs to respond to +the lender's flow. Let's do that by replacing ``Responder`` from the template with the following: + +.. container:: codeset + + .. literalinclude:: example-code/src/main/kotlin/net/corda/docs/kotlin/tutorial/helloworld/IOUFlowResponder.kt + :language: kotlin + :start-after: DOCSTART 01 + :end-before: DOCEND 01 + + .. literalinclude:: example-code/src/main/java/net/corda/docs/java/tutorial/helloworld/IOUFlowResponder.java + :language: java + :start-after: DOCSTART 01 + :end-before: DOCEND 01 + +As with the ``IOUFlow``, our ``IOUFlowResponder`` flow is a ``FlowLogic`` subclass where we've overridden ``FlowLogic.call``. + +The flow is annotated with ``InitiatedBy(IOUFlow.class)``, which means that your node will invoke +``IOUFlowResponder.call`` when it receives a message from a instance of ``Initiator`` running on another node. This message +will be the finalised transaction which will be recorded in the borrower's vault. Progress so far --------------- Our flow, and our CorDapp, are now ready! We have now defined a flow that we can start on our node to completely -automate the process of issuing an IOU onto the ledger. All that's left is to spin up some nodes and test our CorDapp. \ No newline at end of file +automate the process of issuing an IOU onto the ledger. All that's left is to spin up some nodes and test our CorDapp. diff --git a/docs/source/tut-two-party-flow.rst b/docs/source/tut-two-party-flow.rst index 7542eaed14..5c66b3b550 100644 --- a/docs/source/tut-two-party-flow.rst +++ b/docs/source/tut-two-party-flow.rst @@ -65,13 +65,10 @@ transaction proposal before finalising it by adding our signature. Requesting the borrower's signature ----------------------------------- -We now need to communicate with the borrower to request their signature over the transaction. Whenever you want to -communicate with another party in the context of a flow, you first need to establish a flow session with them. If the -counterparty has a ``FlowLogic`` registered to respond to the ``FlowLogic`` initiating the session, a session will be -established. All communication between the two ``FlowLogic`` instances will then place as part of this session. +Previously we wrote a responder flow for the borrower in order to receive the finalised transaction from the lender. +We use this same flow to first request their signature over the transaction. -Once we have a session with the borrower, we gather the borrower's signature using ``CollectSignaturesFlow``, which -takes: +We gather the borrower's signature using ``CollectSignaturesFlow``, which takes: * A transaction signed by the flow initiator * A list of flow-sessions between the flow initiator and the required signers @@ -80,11 +77,11 @@ And returns a transaction signed by all the required signers. We can then pass this fully-signed transaction into ``FinalityFlow``. -Creating the borrower's flow +Updating the borrower's flow ---------------------------- -On the lender's side, we used ``CollectSignaturesFlow`` to automate the collection of signatures. To allow the lender -to respond, we need to write a response flow as well. In a new ``IOUFlowResponder.java`` file in Java, or within the -``App.kt`` file in Kotlin, add the following class: +On the lender's side, we used ``CollectSignaturesFlow`` to automate the collection of signatures. To allow the borrower +to respond, we need to update its responder flow to first receive the partially signed transaction for signing. Update +``IOUFlowResponder.call`` to be the following: .. container:: codeset @@ -92,19 +89,13 @@ to respond, we need to write a response flow as well. In a new ``IOUFlowResponde :language: kotlin :start-after: DOCSTART 01 :end-before: DOCEND 01 + :dedent: 8 .. literalinclude:: example-code/src/main/java/net/corda/docs/java/tutorial/twoparty/IOUFlowResponder.java :language: java :start-after: DOCSTART 01 :end-before: DOCEND 01 - -As with the ``IOUFlow``, our ``IOUFlowResponder`` flow is a ``FlowLogic`` subclass where we've overridden -``FlowLogic.call``. - -The flow is annotated with ``InitiatedBy(IOUFlow.class)``, which means that your node will invoke -``IOUFlowResponder.call`` when it receives a message from a instance of ``Initiator`` running on another node. What -will this message from the ``IOUFlow`` be? If we look at the definition of ``CollectSignaturesFlow``, we can see that -we'll be sent a ``SignedTransaction``, and are expected to send back our signature over that transaction. + :dedent: 8 We could write our own flow to handle this process. However, there is also a pre-defined flow called ``SignTransactionFlow`` that can handle the process automatically. The only catch is that ``SignTransactionFlow`` is an @@ -128,6 +119,9 @@ signatures are contractually valid. Once we've defined the ``SignTransactionFlow`` subclass, we invoke it using ``FlowLogic.subFlow``, and the communication with the borrower's and the lender's flow is conducted automatically. +``SignedTransactionFlow`` returns the newly signed transaction. We pass in the transaction's ID to ``ReceiveFinalityFlow`` +to ensure we are recording the correct notarised transaction from the lender. + Conclusion ---------- We have now updated our flow to verify the transaction and gather the lender's signature, in line with the constraints diff --git a/docs/source/tut-two-party-introduction.rst b/docs/source/tut-two-party-introduction.rst index a12f022a08..193888d438 100644 --- a/docs/source/tut-two-party-introduction.rst +++ b/docs/source/tut-two-party-introduction.rst @@ -7,7 +7,7 @@ In the Hello, World tutorial, we built a CorDapp allowing us to model IOUs on le elements: * An ``IOUState``, representing IOUs on the blockchain -* An ``IOUFlow``, orchestrating the process of agreeing the creation of an IOU on-ledger +* An ``IOUFlow`` and ``IOFlowResponder`` flow pair, orchestrating the process of agreeing the creation of an IOU on-ledger However, our CorDapp did not impose any constraints on the evolution of IOUs on the blockchain over time. Anyone was free to create IOUs of any value, between any party. diff --git a/docs/source/tutorial-building-transactions.rst b/docs/source/tutorial-building-transactions.rst index 2c5ef076b8..32be2f3758 100644 --- a/docs/source/tutorial-building-transactions.rst +++ b/docs/source/tutorial-building-transactions.rst @@ -81,12 +81,10 @@ To give a few more specific details consider two simplified real world scenarios. First, a basic foreign exchange cash transaction. This transaction needs to locate a set of funds to exchange. A flow modelling this is implemented in ``FxTransactionBuildTutorial.kt`` -(see ``docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/FxTransactionBuildTutorial.kt`` in the -`main Corda repo `_). +(in the `main Corda repo `_). Second, a simple business model in which parties manually accept or reject each other's trade proposals, which is implemented in -``WorkflowTransactionBuildTutorial.kt`` (see -``docs/source/example-code/src/main/kotlin/net/corda/docs/kotlin/WorkflowTransactionBuildTutorial.kt`` in the +``WorkflowTransactionBuildTutorial.kt`` (in the `main Corda repo `_). To run and explore these examples using the IntelliJ IDE one can run/step through the respective unit tests in ``FxTransactionBuildTutorialTest.kt`` and @@ -148,7 +146,7 @@ parameters to the flow to identify the states being operated upon. Thus code to gather the latest input state for a given ``StateRef`` would use the ``VaultService`` as follows: -.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/kotlin/WorkflowTransactionBuildTutorial.kt +.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/kotlin/txbuild/WorkflowTransactionBuildTutorial.kt :language: kotlin :start-after: DOCSTART 1 :end-before: DOCEND 1 @@ -221,7 +219,7 @@ and convert it into a ``SignedTransaction``. Examples of this process are: -.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/kotlin/WorkflowTransactionBuildTutorial.kt +.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/kotlin/txbuild/WorkflowTransactionBuildTutorial.kt :language: kotlin :start-after: DOCSTART 2 :end-before: DOCEND 2 @@ -260,7 +258,7 @@ context. For example, the flow may need to check that the parties are the right ones, or that the ``Command`` present on the transaction is as expected for this specific flow. An example of this from the demo code is: -.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/kotlin/WorkflowTransactionBuildTutorial.kt +.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/kotlin/txbuild/WorkflowTransactionBuildTutorial.kt :language: kotlin :start-after: DOCSTART 3 :end-before: DOCEND 3 @@ -277,7 +275,7 @@ Once all the signatures are applied to the ``SignedTransaction``, the final steps are notarisation and ensuring that all nodes record the fully-signed transaction. The code for this is standardised in the ``FinalityFlow``: -.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/kotlin/WorkflowTransactionBuildTutorial.kt +.. literalinclude:: example-code/src/main/kotlin/net/corda/docs/kotlin/txbuild/WorkflowTransactionBuildTutorial.kt :language: kotlin :start-after: DOCSTART 4 :end-before: DOCEND 4 diff --git a/docs/source/tutorial-integration-testing.rst b/docs/source/tutorial-integration-testing.rst index 1647d1bf43..5b2e9c8d98 100644 --- a/docs/source/tutorial-integration-testing.rst +++ b/docs/source/tutorial-integration-testing.rst @@ -21,13 +21,13 @@ a local network where all the nodes see each other and provides safe shutting do .. container:: codeset - .. literalinclude:: example-code/src/integration-test/kotlin/net/corda/docs/KotlinIntegrationTestingTutorial.kt + .. literalinclude:: example-code/src/integration-test/kotlin/net/corda/docs/kotlin/tutorial/test/KotlinIntegrationTestingTutorial.kt :language: kotlin :start-after: START 1 :end-before: END 1 :dedent: 8 - .. literalinclude:: example-code/src/integration-test/java/net/corda/docs/JavaIntegrationTestingTutorial.java + .. literalinclude:: example-code/src/integration-test/java/net/corda/docs/java/tutorial/test/JavaIntegrationTestingTutorial.java :language: java :start-after: START 1 :end-before: END 1 @@ -49,13 +49,13 @@ the information returned; their respective ``NodeHandles`` s. .. container:: codeset - .. literalinclude:: example-code/src/integration-test/kotlin/net/corda/docs/KotlinIntegrationTestingTutorial.kt + .. literalinclude:: example-code/src/integration-test/kotlin/net/corda/docs/kotlin/tutorial/test/KotlinIntegrationTestingTutorial.kt :language: kotlin :start-after: START 2 :end-before: END 2 :dedent: 12 - .. literalinclude:: example-code/src/integration-test/java/net/corda/docs/JavaIntegrationTestingTutorial.java + .. literalinclude:: example-code/src/integration-test/java/net/corda/docs/java/tutorial/test/JavaIntegrationTestingTutorial.java :language: java :start-after: START 2 :end-before: END 2 @@ -66,13 +66,13 @@ us to start flows and query state. .. container:: codeset - .. literalinclude:: example-code/src/integration-test/kotlin/net/corda/docs/KotlinIntegrationTestingTutorial.kt + .. literalinclude:: example-code/src/integration-test/kotlin/net/corda/docs/kotlin/tutorial/test/KotlinIntegrationTestingTutorial.kt :language: kotlin :start-after: START 3 :end-before: END 3 :dedent: 12 - .. literalinclude:: example-code/src/integration-test/java/net/corda/docs/JavaIntegrationTestingTutorial.java + .. literalinclude:: example-code/src/integration-test/java/net/corda/docs/java/tutorial/test/JavaIntegrationTestingTutorial.java :language: java :start-after: START 3 :end-before: END 3 @@ -84,13 +84,13 @@ Now that we're all set up we can finally get some cash action going! .. container:: codeset - .. literalinclude:: example-code/src/integration-test/kotlin/net/corda/docs/KotlinIntegrationTestingTutorial.kt + .. literalinclude:: example-code/src/integration-test/kotlin/net/corda/docs/kotlin/tutorial/test/KotlinIntegrationTestingTutorial.kt :language: kotlin :start-after: START 4 :end-before: END 4 :dedent: 12 - .. literalinclude:: example-code/src/integration-test/java/net/corda/docs/JavaIntegrationTestingTutorial.java + .. literalinclude:: example-code/src/integration-test/java/net/corda/docs/java/tutorial/test/JavaIntegrationTestingTutorial.java :language: java :start-after: START 4 :end-before: END 4 @@ -106,13 +106,13 @@ is asserting. .. container:: codeset - .. literalinclude:: example-code/src/integration-test/kotlin/net/corda/docs/KotlinIntegrationTestingTutorial.kt + .. literalinclude:: example-code/src/integration-test/kotlin/net/corda/docs/kotlin/tutorial/test/KotlinIntegrationTestingTutorial.kt :language: kotlin :start-after: START 5 :end-before: END 5 :dedent: 12 - .. literalinclude:: example-code/src/integration-test/java/net/corda/docs/JavaIntegrationTestingTutorial.java + .. literalinclude:: example-code/src/integration-test/java/net/corda/docs/java/tutorial/test/JavaIntegrationTestingTutorial.java :language: java :start-after: START 5 :end-before: END 5 @@ -123,6 +123,6 @@ Next we want Bob to send this cash back to Alice. That's it! We saw how to start up several corda nodes locally, how to connect to them, and how to test some simple invariants about ``CashIssueAndPaymentFlow`` and ``CashPaymentFlow``. -You can find the complete test at ``example-code/src/integration-test/java/net/corda/docs/JavaIntegrationTestingTutorial.java`` -(Java) and ``example-code/src/integration-test/kotlin/net/corda/docs/KotlinIntegrationTestingTutorial.kt`` (Kotlin) in the +You can find the complete test at ``example-code/src/integration-test/java/net/corda/docs/java/tutorial/test/JavaIntegrationTestingTutorial.java`` +(Java) and ``example-code/src/integration-test/kotlin/net/corda/docs/kotlin/tutorial/test/KotlinIntegrationTestingTutorial.kt`` (Kotlin) in the `Corda repo `_. diff --git a/docs/source/upgrade-notes.rst b/docs/source/upgrade-notes.rst index 161c6d3d0b..c0869c94ab 100644 --- a/docs/source/upgrade-notes.rst +++ b/docs/source/upgrade-notes.rst @@ -1,3 +1,9 @@ +.. highlight:: kotlin +.. raw:: html + + + + Upgrading a CorDapp to a new platform version ============================================= @@ -6,6 +12,106 @@ These notes provide instructions for upgrading your CorDapps from previous versi .. contents:: :depth: 1 +UNRELEASED +---------- + +FinalityFlow +^^^^^^^^^^^^ + +The previous ``FinalityFlow`` API is insecure. It requires a handler flow in the counterparty node which accepts any and +all signed transactions that are sent to it, without checks. It is **highly** recommended that existing CorDapps migrate +away to the new API. + +As an example, let's take a very simple flow that finalises a transaction without the involvement of a counterpart flow: + +.. container:: codeset + + .. literalinclude:: example-code/src/main/kotlin/net/corda/docs/kotlin/FinalityFlowMigration.kt + :language: kotlin + :start-after: DOCSTART SimpleFlowUsingOldApi + :end-before: DOCEND SimpleFlowUsingOldApi + + .. literalinclude:: example-code/src/main/java/net/corda/docs/java/FinalityFlowMigration.java + :language: java + :start-after: DOCSTART SimpleFlowUsingOldApi + :end-before: DOCEND SimpleFlowUsingOldApi + :dedent: 4 + +To use the new API, this flow needs to be annotated with ``InitiatingFlow`` and a ``FlowSession`` to the participant of the transaction must be +passed to ``FinalityFlow`` : + +.. container:: codeset + + .. literalinclude:: example-code/src/main/kotlin/net/corda/docs/kotlin/FinalityFlowMigration.kt + :language: kotlin + :start-after: DOCSTART SimpleFlowUsingNewApi + :end-before: DOCEND SimpleFlowUsingNewApi + + .. literalinclude:: example-code/src/main/java/net/corda/docs/java/FinalityFlowMigration.java + :language: java + :start-after: DOCSTART SimpleFlowUsingNewApi + :end-before: DOCEND SimpleFlowUsingNewApi + :dedent: 4 + +If there are more than one transaction participants then a session to each one must be initiated, excluding the local party +and the notary. + +A responder flow has to be introduced, which will automatically run on the other participants' nodes, which will call ``ReceiveFinalityFlow`` +to record the finalised transaction: + +.. container:: codeset + + .. literalinclude:: example-code/src/main/kotlin/net/corda/docs/kotlin/FinalityFlowMigration.kt + :language: kotlin + :start-after: DOCSTART SimpleNewResponderFlow + :end-before: DOCEND SimpleNewResponderFlow + + .. literalinclude:: example-code/src/main/java/net/corda/docs/java/FinalityFlowMigration.java + :language: java + :start-after: DOCSTART SimpleNewResponderFlow + :end-before: DOCEND SimpleNewResponderFlow + :dedent: 4 + +For flows which are already initiating counterpart flows then it's a simple matter of using the existing flow session. +Note however, the new ``FinalityFlow`` is inlined and so the sequence of sends and receives between the two flows will +change and will be incompatible with your current flows. You can use the flow version API to write your flows in a +backwards compatible way. + +Here's what an upgraded initiating flow may look like: + +.. container:: codeset + + .. literalinclude:: example-code/src/main/kotlin/net/corda/docs/kotlin/FinalityFlowMigration.kt + :language: kotlin + :start-after: DOCSTART ExistingInitiatingFlow + :end-before: DOCEND ExistingInitiatingFlow + + .. literalinclude:: example-code/src/main/java/net/corda/docs/java/FinalityFlowMigration.java + :language: java + :start-after: DOCSTART ExistingInitiatingFlow + :end-before: DOCEND ExistingInitiatingFlow + :dedent: 4 + +For the responder flow, insert a call to ``ReceiveFinalityFlow`` at the location where it's expecting to receive the +finalised transaction. If the initiator is written in a backwards compatible way then so must the responder. + +.. container:: codeset + + .. literalinclude:: example-code/src/main/kotlin/net/corda/docs/kotlin/FinalityFlowMigration.kt + :language: kotlin + :start-after: DOCSTART ExistingResponderFlow + :end-before: DOCEND ExistingResponderFlow + :dedent: 8 + + .. literalinclude:: example-code/src/main/java/net/corda/docs/java/FinalityFlowMigration.java + :language: java + :start-after: DOCSTART ExistingResponderFlow + :end-before: DOCEND ExistingResponderFlow + :dedent: 12 + +The responder flow may be waiting for the finalised transaction to appear in the local node's vault using ``waitForLedgerCommit``. +This is no longer necessary with ``ReceiveFinalityFlow`` and the call to ``waitForLedgerCommit`` can be removed. + Upgrading from Corda Open Source -------------------------------- diff --git a/experimental/corda-utils/src/main/kotlin/io/cryptoblk/core/Utils.kt b/experimental/corda-utils/src/main/kotlin/io/cryptoblk/core/Utils.kt index 0c3ab7a203..0d37af738c 100644 --- a/experimental/corda-utils/src/main/kotlin/io/cryptoblk/core/Utils.kt +++ b/experimental/corda-utils/src/main/kotlin/io/cryptoblk/core/Utils.kt @@ -19,16 +19,6 @@ inline fun ServiceHub.queryStateByRef(ref: StateRef) return results.states.firstOrNull() ?: throw IllegalArgumentException("State (type=${T::class}) corresponding to the reference $ref not found (or is spent).") } -/** - * Shorthand when a single party signs a TX and then returns a result that uses the signed TX (e.g. includes the TX id) - */ -@Suspendable -fun FlowLogic.finalize(tx: TransactionBuilder, returnWithSignedTx: (stx: SignedTransaction) -> R): R { - val stx = serviceHub.signInitialTransaction(tx) - subFlow(FinalityFlow(stx)) // it'll send to all participants in the state by default - return returnWithSignedTx(stx) -} - /** * Corda fails when it tries to store the same attachment hash twice. And it's convenient to also do nothing if no attachment is provided. * This doesn't fix the same-attachment problem completely but should at least help in testing with the same file. diff --git a/finance/src/main/kotlin/net/corda/finance/flows/AbstractCashFlow.kt b/finance/src/main/kotlin/net/corda/finance/flows/AbstractCashFlow.kt index b47592a5e8..07ca3a2078 100644 --- a/finance/src/main/kotlin/net/corda/finance/flows/AbstractCashFlow.kt +++ b/finance/src/main/kotlin/net/corda/finance/flows/AbstractCashFlow.kt @@ -2,12 +2,8 @@ package net.corda.finance.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.Amount -import net.corda.core.flows.FinalityFlow -import net.corda.core.flows.FlowException -import net.corda.core.flows.FlowLogic -import net.corda.core.flows.NotaryException +import net.corda.core.flows.* import net.corda.core.identity.AbstractParty -import net.corda.core.identity.Party import net.corda.core.serialization.CordaSerializable import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.ProgressTracker @@ -27,9 +23,9 @@ abstract class AbstractCashFlow(override val progressTracker: ProgressTra } @Suspendable - protected fun finaliseTx(tx: SignedTransaction, extraParticipants: Set, message: String): SignedTransaction { + protected fun finaliseTx(tx: SignedTransaction, sessions: Collection, message: String): SignedTransaction { try { - return subFlow(FinalityFlow(tx, extraParticipants)) + return subFlow(FinalityFlow(tx, sessions)) } catch (e: NotaryException) { throw CashException(message, e) } diff --git a/finance/src/main/kotlin/net/corda/finance/flows/CashExitFlow.kt b/finance/src/main/kotlin/net/corda/finance/flows/CashExitFlow.kt index 750437ad83..1b92e51df9 100644 --- a/finance/src/main/kotlin/net/corda/finance/flows/CashExitFlow.kt +++ b/finance/src/main/kotlin/net/corda/finance/flows/CashExitFlow.kt @@ -3,8 +3,7 @@ package net.corda.finance.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.Amount import net.corda.core.contracts.InsufficientBalanceException -import net.corda.core.flows.StartableByRPC -import net.corda.core.identity.Party +import net.corda.core.flows.* import net.corda.core.node.services.queryBy import net.corda.core.node.services.vault.DEFAULT_PAGE_NUM import net.corda.core.node.services.vault.PageSpecification @@ -28,6 +27,7 @@ import java.util.* * @param issuerRef the reference on the issued currency. Added to the node's legal identity to determine the * issuer. */ +@InitiatingFlow @StartableByRPC class CashExitFlow(private val amount: Amount, private val issuerRef: OpaqueBytes, @@ -53,7 +53,7 @@ class CashExitFlow(private val amount: Amount, .getInstance { serviceHub.jdbcSession().metaData } .unconsumedCashStatesForSpending(serviceHub, amount, setOf(issuer.party), builder.notary, builder.lockId, setOf(issuer.reference)) val signers = try { - val changeOwner = exitStates.map { it.state.data.owner }.toSet().firstOrNull() ?: throw InsufficientBalanceException(amount) + val changeOwner = exitStates.asSequence().map { it.state.data.owner }.toSet().firstOrNull() ?: throw InsufficientBalanceException(amount) Cash().generateExit( builder, amount.issuedBy(issuer), @@ -67,21 +67,31 @@ class CashExitFlow(private val amount: Amount, val inputStates = serviceHub.vaultService.queryBy(VaultQueryCriteria(stateRefs = builder.inputStates()), PageSpecification(pageNumber = DEFAULT_PAGE_NUM, pageSize = builder.inputStates().size)).states - // TODO: Is it safe to drop participants we don't know how to contact? Does not knowing how to contact them - // count as a reason to fail? - val participants: Set = inputStates + val participantSessions = inputStates + .asSequence() .mapNotNull { serviceHub.identityService.wellKnownPartyFromAnonymous(it.state.data.owner) } - .toSet() + .filterNot(serviceHub.myInfo::isLegalIdentity) + .distinct() + .map(::initiateFlow) + .toList() // Sign transaction progressTracker.currentStep = SIGNING_TX val tx = serviceHub.signInitialTransaction(builder, signers) // Commit the transaction progressTracker.currentStep = FINALISING_TX - val notarised = finaliseTx(tx, participants, "Unable to notarise exit") + val notarised = finaliseTx(tx, participantSessions, "Unable to notarise exit") return Result(notarised, null) } @CordaSerializable class ExitRequest(amount: Amount, val issuerRef: OpaqueBytes) : AbstractRequest(amount) } + +@InitiatedBy(CashExitFlow::class) +class CashExitResponderFlow(private val otherSide: FlowSession) : FlowLogic() { + @Suspendable + override fun call() { + subFlow(ReceiveFinalityFlow(otherSide)) + } +} diff --git a/finance/src/main/kotlin/net/corda/finance/flows/CashPaymentFlow.kt b/finance/src/main/kotlin/net/corda/finance/flows/CashPaymentFlow.kt index b5147fb0f5..9eca7ca3df 100644 --- a/finance/src/main/kotlin/net/corda/finance/flows/CashPaymentFlow.kt +++ b/finance/src/main/kotlin/net/corda/finance/flows/CashPaymentFlow.kt @@ -4,7 +4,7 @@ import co.paralleluniverse.fibers.Suspendable import net.corda.confidential.SwapIdentitiesFlow import net.corda.core.contracts.Amount import net.corda.core.contracts.InsufficientBalanceException -import net.corda.core.flows.StartableByRPC +import net.corda.core.flows.* import net.corda.core.identity.AnonymousParty import net.corda.core.identity.Party import net.corda.core.serialization.CordaSerializable @@ -28,6 +28,7 @@ import java.util.* * for testing purposes. */ @StartableByRPC +@InitiatingFlow open class CashPaymentFlow( val amount: Amount, val recipient: Party, @@ -75,7 +76,8 @@ open class CashPaymentFlow( progressTracker.currentStep = FINALISING_TX logger.info("Finalising transaction for: ${tx.id}") - val notarised = finaliseTx(tx, setOf(recipient), "Unable to notarise spend") + val sessions = if (serviceHub.myInfo.isLegalIdentity(recipient)) emptyList() else listOf(initiateFlow(recipient)) + val notarised = finaliseTx(tx, sessions, "Unable to notarise spend") logger.info("Finalised transaction for: ${notarised.id}") return Result(notarised, anonymousRecipient) } @@ -87,3 +89,11 @@ open class CashPaymentFlow( val issuerConstraint: Set = emptySet(), val notary: Party? = null) : AbstractRequest(amount) } + +@InitiatedBy(CashPaymentFlow::class) +class CashPaymentResponderFlow(private val otherSide: FlowSession) : FlowLogic() { + @Suspendable + override fun call() { + subFlow(ReceiveFinalityFlow(otherSide)) + } +} diff --git a/finance/src/main/kotlin/net/corda/finance/flows/TwoPartyDealFlow.kt b/finance/src/main/kotlin/net/corda/finance/flows/TwoPartyDealFlow.kt index b1dd0137aa..93d7430f5b 100644 --- a/finance/src/main/kotlin/net/corda/finance/flows/TwoPartyDealFlow.kt +++ b/finance/src/main/kotlin/net/corda/finance/flows/TwoPartyDealFlow.kt @@ -71,7 +71,7 @@ object TwoPartyDealFlow { val txId = subFlow(signTransactionFlow).id - return waitForLedgerCommit(txId) + return subFlow(ReceiveFinalityFlow(otherSideSession, expectedTxId = txId)) } @Suspendable @@ -81,8 +81,7 @@ object TwoPartyDealFlow { /** * Abstracted bilateral deal flow participant that is recipient of initial communication. */ - abstract class Secondary(override val progressTracker: ProgressTracker = Secondary.tracker(), - val regulators: Set = emptySet()) : FlowLogic() { + abstract class Secondary(override val progressTracker: ProgressTracker = Secondary.tracker()) : FlowLogic() { companion object { object RECEIVING : ProgressTracker.Step("Waiting for deal info.") @@ -124,7 +123,7 @@ object TwoPartyDealFlow { logger.trace("Got signatures from other party, verifying ... ") progressTracker.currentStep = RECORDING - val ftx = subFlow(FinalityFlow(stx, regulators + otherSideSession.counterparty)) + val ftx = subFlow(FinalityFlow(stx, otherSideSession)) logger.trace("Recorded transaction.") return ftx diff --git a/finance/src/main/kotlin/net/corda/finance/flows/TwoPartyTradeFlow.kt b/finance/src/main/kotlin/net/corda/finance/flows/TwoPartyTradeFlow.kt index 28e98035c7..57c79cf191 100644 --- a/finance/src/main/kotlin/net/corda/finance/flows/TwoPartyTradeFlow.kt +++ b/finance/src/main/kotlin/net/corda/finance/flows/TwoPartyTradeFlow.kt @@ -114,7 +114,7 @@ object TwoPartyTradeFlow { val txId = subFlow(signTransactionFlow).id // DOCEND 5 - return waitForLedgerCommit(txId) + return subFlow(ReceiveFinalityFlow(otherSideSession, expectedTxId = txId)) } // DOCEND 4 @@ -188,7 +188,7 @@ object TwoPartyTradeFlow { // Notarise and record the transaction. progressTracker.currentStep = RECORDING - return subFlow(FinalityFlow(twiceSignedTx)) + return subFlow(FinalityFlow(twiceSignedTx, sellerSession)) } @Suspendable diff --git a/finance/src/test/kotlin/net/corda/finance/flows/CashPaymentFlowTests.kt b/finance/src/test/kotlin/net/corda/finance/flows/CashPaymentFlowTests.kt index 8b9ba26423..b87ece636b 100644 --- a/finance/src/test/kotlin/net/corda/finance/flows/CashPaymentFlowTests.kt +++ b/finance/src/test/kotlin/net/corda/finance/flows/CashPaymentFlowTests.kt @@ -13,6 +13,7 @@ import net.corda.testing.core.* import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin import net.corda.testing.node.MockNetwork import net.corda.testing.node.StartedMockNode +import org.assertj.core.api.Assertions.assertThat import org.junit.After import org.junit.Before import org.junit.Test @@ -29,7 +30,7 @@ class CashPaymentFlowTests { @Before fun start() { - mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin(), cordappPackages = listOf("net.corda.finance.contracts.asset", "net.corda.finance.schemas")) + mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin(), cordappPackages = listOf("net.corda.finance")) bankOfCordaNode = mockNet.createPartyNode(BOC_NAME) bankOfCorda = bankOfCordaNode.info.identityFromX500Name(BOC_NAME) aliceNode = mockNet.createPartyNode(ALICE_NAME) @@ -61,10 +62,10 @@ class CashPaymentFlowTests { // Check Bank of Corda vault updates - we take in some issued cash and split it into $500 to the notary // and $1,500 back to us, so we expect to consume one state, produce one state for our own vault vaultUpdatesBoc.expectEvents { - expect { update -> - require(update.consumed.size == 1) { "Expected 1 consumed states, actual: $update" } - require(update.produced.size == 1) { "Expected 1 produced states, actual: $update" } - val changeState = update.produced.single().state.data + expect { (consumed, produced) -> + assertThat(consumed).hasSize(1) + assertThat(produced).hasSize(1) + val changeState = produced.single().state.data assertEquals(expectedChange.`issued by`(bankOfCorda.ref(ref)), changeState.amount) } } @@ -72,8 +73,8 @@ class CashPaymentFlowTests { // Check notary node vault updates vaultUpdatesBankClient.expectEvents { expect { (consumed, produced) -> - require(consumed.isEmpty()) { consumed.size } - require(produced.size == 1) { produced.size } + assertThat(consumed).isEmpty() + assertThat(produced).hasSize(1) val paymentState = produced.single().state.data assertEquals(expectedPayment.`issued by`(bankOfCorda.ref(ref)), paymentState.amount) } diff --git a/node/src/integration-test/kotlin/net/corda/node/modes/draining/FlowsDrainingModeContentionTest.kt b/node/src/integration-test/kotlin/net/corda/node/modes/draining/FlowsDrainingModeContentionTest.kt index 48a7001aec..8d2a07c736 100644 --- a/node/src/integration-test/kotlin/net/corda/node/modes/draining/FlowsDrainingModeContentionTest.kt +++ b/node/src/integration-test/kotlin/net/corda/node/modes/draining/FlowsDrainingModeContentionTest.kt @@ -43,7 +43,6 @@ class FlowsDrainingModeContentionTest : IntegrationTest() { @JvmField val databaseSchemas = IntegrationTestSchemas(ALICE_NAME.toDatabaseSchemaName(), BOB_NAME.toDatabaseSchemaName(), DUMMY_NOTARY_NAME.toDatabaseSchemaName()) } - private val portAllocation = PortAllocation.Incremental(10000) private val user = User("mark", "dadada", setOf(all())) private val users = listOf(user) @@ -100,7 +99,7 @@ class ProposeTransactionAndWaitForCommit(private val data: String, subFlow(SendTransactionFlow(session, signedTx)) session.send(myRpcInfo) - return waitForLedgerCommit(signedTx.id) + return subFlow(ReceiveFinalityFlow(session, expectedTxId = signedTx.id)) } } @@ -114,7 +113,7 @@ class SignTransactionTriggerDrainingModeAndFinality(private val session: FlowSes triggerDrainingModeForInitiatingNode(initiatingRpcInfo) - subFlow(FinalityFlow(signedTx, setOf(session.counterparty))) + subFlow(FinalityFlow(signedTx, session)) } private fun triggerDrainingModeForInitiatingNode(initiatingRpcInfo: RpcInfo) { diff --git a/node/src/integration-test/kotlin/net/corda/node/persistence/NodeStatePersistenceTests.kt b/node/src/integration-test/kotlin/net/corda/node/persistence/NodeStatePersistenceTests.kt index c6b0abd39c..7a01d4f9ba 100644 --- a/node/src/integration-test/kotlin/net/corda/node/persistence/NodeStatePersistenceTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/persistence/NodeStatePersistenceTests.kt @@ -147,6 +147,6 @@ class SendMessageFlow(private val message: Message, private val notary: Party) : val signedTx = serviceHub.signInitialTransaction(txBuilder) progressTracker.currentStep = FINALISING_TRANSACTION - return subFlow(FinalityFlow(signedTx, FINALISING_TRANSACTION.childProgressTracker())) + return subFlow(FinalityFlow(signedTx, emptyList(), FINALISING_TRANSACTION.childProgressTracker())) } } \ No newline at end of file diff --git a/node/src/integration-test/kotlin/net/corda/node/services/events/ScheduledFlowIntegrationTests.kt b/node/src/integration-test/kotlin/net/corda/node/services/events/ScheduledFlowIntegrationTests.kt index f8e79ff548..444b2226ee 100644 --- a/node/src/integration-test/kotlin/net/corda/node/services/events/ScheduledFlowIntegrationTests.kt +++ b/node/src/integration-test/kotlin/net/corda/node/services/events/ScheduledFlowIntegrationTests.kt @@ -4,9 +4,7 @@ import co.paralleluniverse.fibers.Suspendable import com.google.common.collect.ImmutableList import net.corda.client.rpc.CordaRPCClient import net.corda.core.concurrent.CordaFuture -import net.corda.core.flows.FinalityFlow -import net.corda.core.flows.FlowLogic -import net.corda.core.flows.StartableByRPC +import net.corda.core.flows.* import net.corda.core.identity.Party import net.corda.core.internal.concurrent.transpose import net.corda.core.messaging.startFlow @@ -46,6 +44,7 @@ class ScheduledFlowIntegrationTests : IntegrationTest() { } @StartableByRPC + @InitiatingFlow class InsertInitialStateFlow(private val destination: Party, private val notary: Party, private val identity: Int = 1, @@ -58,11 +57,20 @@ class ScheduledFlowIntegrationTests : IntegrationTest() { .addOutputState(scheduledState, DummyContract.PROGRAM_ID) .addCommand(dummyCommand(ourIdentity.owningKey)) val tx = serviceHub.signInitialTransaction(builder) - subFlow(FinalityFlow(tx)) + subFlow(FinalityFlow(tx, initiateFlow(destination))) + } + } + + @InitiatedBy(InsertInitialStateFlow::class) + class InsertInitialStateResponderFlow(private val otherSide: FlowSession) : FlowLogic() { + @Suspendable + override fun call() { + subFlow(ReceiveFinalityFlow(otherSide)) } } @StartableByRPC + @InitiatingFlow class AnotherFlow(private val identity: String) : FlowLogic() { @Suspendable override fun call() { @@ -78,7 +86,15 @@ class ScheduledFlowIntegrationTests : IntegrationTest() { .addOutputState(outputState, DummyContract.PROGRAM_ID) .addCommand(dummyCommand(ourIdentity.owningKey)) val tx = serviceHub.signInitialTransaction(builder) - subFlow(FinalityFlow(tx, outputState.participants.toSet())) + subFlow(FinalityFlow(tx, initiateFlow(state.state.data.destination))) + } + } + + @InitiatedBy(AnotherFlow::class) + class AnotherResponderFlow(private val otherSide: FlowSession) : FlowLogic() { + @Suspendable + override fun call() { + subFlow(ReceiveFinalityFlow(otherSide)) } } diff --git a/node/src/integration-test/kotlin/net/corda/testMessage/ScheduledState.kt b/node/src/integration-test/kotlin/net/corda/testMessage/ScheduledState.kt index 189d0fc9f4..dfa3390387 100644 --- a/node/src/integration-test/kotlin/net/corda/testMessage/ScheduledState.kt +++ b/node/src/integration-test/kotlin/net/corda/testMessage/ScheduledState.kt @@ -2,10 +2,7 @@ package net.corda.testMessage import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.* -import net.corda.core.flows.FinalityFlow -import net.corda.core.flows.FlowLogic -import net.corda.core.flows.FlowLogicRefFactory -import net.corda.core.flows.SchedulableFlow +import net.corda.core.flows.* import net.corda.core.identity.Party import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.NonEmptySet @@ -16,6 +13,7 @@ import java.util.* import kotlin.reflect.jvm.jvmName @SchedulableFlow +@InitiatingFlow class ScheduledFlow(private val stateRef: StateRef) : FlowLogic() { @Suspendable override fun call() { @@ -35,7 +33,15 @@ class ScheduledFlow(private val stateRef: StateRef) : FlowLogic() { .addOutputState(newStateOutput, DummyContract.PROGRAM_ID) .addCommand(dummyCommand(ourIdentity.owningKey)) val tx = serviceHub.signInitialTransaction(builder) - subFlow(FinalityFlow(tx, setOf(scheduledState.destination))) + subFlow(FinalityFlow(tx, initiateFlow(scheduledState.destination))) + } +} + +@InitiatedBy(ScheduledFlow::class) +class ScheduledResponderFlow(private val otherSide: FlowSession) : FlowLogic() { + @Suspendable + override fun call() { + subFlow(ReceiveFinalityFlow(otherSide)) } } diff --git a/node/src/integration-test/kotlin/net/test/cordapp/v1/FlowCheckpointCordapp.kt b/node/src/integration-test/kotlin/net/test/cordapp/v1/FlowCheckpointCordapp.kt index e32f106338..1d22dddca6 100644 --- a/node/src/integration-test/kotlin/net/test/cordapp/v1/FlowCheckpointCordapp.kt +++ b/node/src/integration-test/kotlin/net/test/cordapp/v1/FlowCheckpointCordapp.kt @@ -49,9 +49,9 @@ class SendMessageFlow(private val message: Message, private val notary: Party, p return if (reciepent != null) { val session = initiateFlow(reciepent) subFlow(SendTransactionFlow(session, signedTx)) - subFlow(FinalityFlow(signedTx, setOf(reciepent), FINALISING_TRANSACTION.childProgressTracker())) + subFlow(FinalityFlow(signedTx, listOf(session), FINALISING_TRANSACTION.childProgressTracker())) } else { - subFlow(FinalityFlow(signedTx, FINALISING_TRANSACTION.childProgressTracker())) + subFlow(FinalityFlow(signedTx, emptyList(), FINALISING_TRANSACTION.childProgressTracker())) } } } 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 96f92bca01..e2bec40012 100644 --- a/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt +++ b/node/src/main/kotlin/net/corda/node/internal/AbstractNode.kt @@ -663,12 +663,39 @@ abstract class AbstractNode(val configuration: NodeConfiguration, } private fun installCoreFlows() { - flowManager.registerInitiatedCoreFlowFactory(FinalityFlow::class, FinalityHandler::class, ::FinalityHandler) + installFinalityHandler() flowManager.registerInitiatedCoreFlowFactory(NotaryChangeFlow::class, NotaryChangeHandler::class, ::NotaryChangeHandler) flowManager.registerInitiatedCoreFlowFactory(ContractUpgradeFlow.Initiate::class, NotaryChangeHandler::class, ::ContractUpgradeHandler) + // TODO Make this an inlined flow (and remove this flow mapping!), which should be possible now that FinalityFlow is also inlined flowManager.registerInitiatedCoreFlowFactory(SwapIdentitiesFlow::class, SwapIdentitiesHandler::class, ::SwapIdentitiesHandler) } + // The FinalityHandler is insecure as it blindly accepts any and all transactions into the node's local vault without doing any checks. + // To plug this hole, the sending-side FinalityFlow has been made inlined with an inlined ReceiveFinalityFlow counterpart. The old + // FinalityFlow API is gated to only work with old CorDapps (those whose target platform version < 4), and the FinalityHandler will only + // work if there is at least one old CorDapp loaded (to preserve backwards compatibility). + // + // If an attempt is made to send us a transaction via FinalityHandler, and it's disabled, we will reject the request at the session-init + // level by throwing a FinalityHandlerDisabled exception. This is picked up by the flow hospital which will not send the error back + // (immediately) and instead pause the request by keeping it un-acknowledged in the message broker. This means the request isn't lost + // across node restarts and allows the node operator time to accept or reject the request. + // TODO Add public API to allow the node operator to accept or reject + private fun installFinalityHandler() { + // Disable the insecure FinalityHandler if none of the loaded CorDapps are old enough to require it. + val cordappsNeedingFinalityHandler = cordappLoader.cordapps.filter { it.info.targetPlatformVersion < 4 } + if (cordappsNeedingFinalityHandler.isEmpty()) { + log.info("FinalityHandler is disabled as there are no CorDapps loaded which require it") + } else { + log.warn("FinalityHandler is enabled as there are CorDapps that require it: ${cordappsNeedingFinalityHandler.map { it.info }}. " + + "This is insecure and it is strongly recommended that newer versions of these CorDapps be used instead.") + } + val disabled = cordappsNeedingFinalityHandler.isEmpty() + flowManager.registerInitiatedCoreFlowFactory(FinalityFlow::class, FinalityHandler::class) { + if (disabled) throw SessionRejectException.FinalityHandlerDisabled() + FinalityHandler(it) + } + } + protected open fun makeTransactionStorage(transactionCacheSizeBytes: Long): WritableTransactionStorage { return DBTransactionStorage(database, cacheFactory) } diff --git a/node/src/main/kotlin/net/corda/node/services/CoreFlowHandlers.kt b/node/src/main/kotlin/net/corda/node/services/CoreFlowHandlers.kt index 7b6bbb75a6..b99a1ce6bd 100644 --- a/node/src/main/kotlin/net/corda/node/services/CoreFlowHandlers.kt +++ b/node/src/main/kotlin/net/corda/node/services/CoreFlowHandlers.kt @@ -7,21 +7,15 @@ import net.corda.core.contracts.requireThat import net.corda.core.flows.* import net.corda.core.identity.Party import net.corda.core.internal.ContractUpgradeUtils -import net.corda.core.transactions.ContractUpgradeWireTransaction import net.corda.core.node.StatesToRecord +import net.corda.core.transactions.ContractUpgradeWireTransaction import net.corda.core.transactions.SignedTransaction -// TODO: We should have a whitelist of contracts we're willing to accept at all, and reject if the transaction -// includes us in any outside that list. Potentially just if it includes any outside that list at all. -// TODO: Do we want to be able to reject specific transactions on more complex rules, for example reject incoming -// cash without from unknown parties? -class FinalityHandler(private val sender: FlowSession) : FlowLogic() { +class FinalityHandler(val sender: FlowSession) : FlowLogic() { @Suspendable override fun call() { subFlow(ReceiveTransactionFlow(sender, true, StatesToRecord.ONLY_RELEVANT)) } - - internal fun sender(): Party = sender.counterparty } class NotaryChangeHandler(otherSideSession: FlowSession) : AbstractStateReplacementFlow.Acceptor(otherSideSession) { @@ -54,10 +48,13 @@ class ContractUpgradeHandler(otherSide: FlowSession) : AbstractStateReplacementF override fun verifyProposal(stx: SignedTransaction, proposal: AbstractStateReplacementFlow.Proposal>>) { // Retrieve signed transaction from our side, we will apply the upgrade logic to the transaction on our side, and // verify outputs matches the proposed upgrade. - val ourSTX = serviceHub.validatedTransactions.getTransaction(proposal.stateRef.txhash) - requireNotNull(ourSTX) { "We don't have a copy of the referenced state" } - val oldStateAndRef = ourSTX!!.resolveBaseTransaction(serviceHub).outRef(proposal.stateRef.index) - val authorisedUpgrade = serviceHub.contractUpgradeService.getAuthorisedContractUpgrade(oldStateAndRef.ref) ?: throw IllegalStateException("Contract state upgrade is unauthorised. State hash : ${oldStateAndRef.ref}") + val ourSTX = requireNotNull(serviceHub.validatedTransactions.getTransaction(proposal.stateRef.txhash)) { + "We don't have a copy of the referenced state" + } + val oldStateAndRef = ourSTX.resolveBaseTransaction(serviceHub).outRef(proposal.stateRef.index) + val authorisedUpgrade = checkNotNull(serviceHub.contractUpgradeService.getAuthorisedContractUpgrade(oldStateAndRef.ref)) { + "Contract state upgrade is unauthorised. State hash : ${oldStateAndRef.ref}" + } val proposedTx = stx.coreTransaction as ContractUpgradeWireTransaction val expectedTx = ContractUpgradeUtils.assembleUpgradeTx(oldStateAndRef, proposal.modification, proposedTx.privacySalt, serviceHub) requireThat { diff --git a/node/src/main/kotlin/net/corda/node/services/statemachine/SessionRejectException.kt b/node/src/main/kotlin/net/corda/node/services/statemachine/SessionRejectException.kt index 55282c558c..e707ddbe7d 100644 --- a/node/src/main/kotlin/net/corda/node/services/statemachine/SessionRejectException.kt +++ b/node/src/main/kotlin/net/corda/node/services/statemachine/SessionRejectException.kt @@ -12,5 +12,8 @@ open class SessionRejectException(message: String) : CordaException(message) { class NotAFlow(val initiatorClass: Class<*>) : SessionRejectException("${initiatorClass.name} is not a flow") class NotRegistered(val initiatorFlowClass: Class>) : SessionRejectException("${initiatorFlowClass.name} is not registered") -} + class FinalityHandlerDisabled : SessionRejectException("Counterparty attempting to use the old insecure API of FinalityFlow. However this " + + "API is disabled on this node since there no CorDapps installed that require it. It may be that the counterparty is running an " + + "older verison of a CorDapp.") +} diff --git a/node/src/main/kotlin/net/corda/node/services/statemachine/StaffedFlowHospital.kt b/node/src/main/kotlin/net/corda/node/services/statemachine/StaffedFlowHospital.kt index f29749566c..3181b9ac37 100644 --- a/node/src/main/kotlin/net/corda/node/services/statemachine/StaffedFlowHospital.kt +++ b/node/src/main/kotlin/net/corda/node/services/statemachine/StaffedFlowHospital.kt @@ -42,6 +42,9 @@ class StaffedFlowHospital(private val flowMessaging: FlowMessaging, private val // installed on restart, at which point the message will be able proceed as normal. If not then it will need // to be dropped manually. Outcome.OVERNIGHT_OBSERVATION + } else if (error is SessionRejectException.FinalityHandlerDisabled) { + // TODO We need a way to be able to give the green light to such a session-init message + Outcome.OVERNIGHT_OBSERVATION } else { Outcome.UNTREATABLE } @@ -284,7 +287,8 @@ class StaffedFlowHospital(private val flowMessaging: FlowMessaging, private val private fun warn(flowLogic: FinalityHandler, flowFiber: FlowFiber, currentState: StateMachineState) { log.warn("Flow ${flowFiber.id} failed to be finalised. Manual intervention may be required before retrying " + - "the flow by re-starting the node. State machine state: $currentState, initiating party was: ${flowLogic.sender().name}") + "the flow by re-starting the node. State machine state: $currentState, initiating party was: " + + "${flowLogic.sender.counterparty}") } } } diff --git a/node/src/test/kotlin/net/corda/node/modes/draining/ScheduledFlowsDrainingModeTest.kt b/node/src/test/kotlin/net/corda/node/modes/draining/ScheduledFlowsDrainingModeTest.kt index ba34d75539..55b9b4d4c8 100644 --- a/node/src/test/kotlin/net/corda/node/modes/draining/ScheduledFlowsDrainingModeTest.kt +++ b/node/src/test/kotlin/net/corda/node/modes/draining/ScheduledFlowsDrainingModeTest.kt @@ -2,11 +2,9 @@ package net.corda.node.modes.draining import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.* -import net.corda.core.flows.FinalityFlow -import net.corda.core.flows.FlowLogic -import net.corda.core.flows.FlowLogicRefFactory -import net.corda.core.flows.SchedulableFlow +import net.corda.core.flows.* import net.corda.core.identity.Party +import net.corda.core.internal.packageName import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.contextLogger import net.corda.core.utilities.getOrThrow @@ -43,7 +41,10 @@ class ScheduledFlowsDrainingModeTest { @Before fun setup() { - mockNet = InternalMockNetwork(cordappsForAllNodes = cordappsForPackages("net.corda.testing.contracts"), threadPerNode = true) + mockNet = InternalMockNetwork( + cordappsForAllNodes = cordappsForPackages("net.corda.testing.contracts", javaClass.packageName), + threadPerNode = true + ) aliceNode = mockNet.createNode(InternalMockNodeParameters(legalName = ALICE_NAME)) bobNode = mockNet.createNode(InternalMockNodeParameters(legalName = BOB_NAME)) notary = mockNet.defaultNotaryIdentity @@ -112,6 +113,7 @@ class ScheduledFlowsDrainingModeTest { override val participants: List get() = listOf(source, destination) } + @InitiatingFlow class InsertInitialStateFlow(private val destination: Party, private val notary: Party) : FlowLogic() { @Suspendable override fun call() { @@ -120,11 +122,20 @@ class ScheduledFlowsDrainingModeTest { .addOutputState(scheduledState, DummyContract.PROGRAM_ID) .addCommand(dummyCommand(ourIdentity.owningKey)) val tx = serviceHub.signInitialTransaction(builder) - subFlow(FinalityFlow(tx)) + subFlow(FinalityFlow(tx, initiateFlow(destination))) + } + } + + @InitiatedBy(InsertInitialStateFlow::class) + class InsertInitialStateResponderFlow(private val otherSide: FlowSession) : FlowLogic() { + @Suspendable + override fun call() { + subFlow(ReceiveFinalityFlow(otherSide)) } } @SchedulableFlow + @InitiatingFlow class ScheduledFlow(private val stateRef: StateRef) : FlowLogic() { @Suspendable override fun call() { @@ -142,7 +153,15 @@ class ScheduledFlowsDrainingModeTest { .addOutputState(newStateOutput, DummyContract.PROGRAM_ID) .addCommand(dummyCommand(ourIdentity.owningKey)) val tx = serviceHub.signInitialTransaction(builder) - subFlow(FinalityFlow(tx, setOf(scheduledState.destination))) + subFlow(FinalityFlow(tx, initiateFlow(scheduledState.destination))) + } + } + + @InitiatedBy(ScheduledFlow::class) + class ScheduledResponderFlow(private val otherSide: FlowSession) : FlowLogic() { + @Suspendable + override fun call() { + subFlow(ReceiveFinalityFlow(otherSide)) } } } diff --git a/node/src/test/kotlin/net/corda/node/services/FinalityHandlerTest.kt b/node/src/test/kotlin/net/corda/node/services/FinalityHandlerTest.kt index c68a0f2ad6..af526f905a 100644 --- a/node/src/test/kotlin/net/corda/node/services/FinalityHandlerTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/FinalityHandlerTest.kt @@ -1,8 +1,12 @@ package net.corda.node.services +import net.corda.core.concurrent.CordaFuture +import net.corda.core.contracts.TransactionVerificationException import net.corda.core.crypto.SecureHash import net.corda.core.flows.FinalityFlow import net.corda.core.flows.StateMachineRunId +import net.corda.core.internal.cordapp.CordappInfoResolver +import net.corda.core.internal.packageName import net.corda.core.toFuture import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder @@ -16,8 +20,10 @@ import net.corda.testing.core.BOB_NAME import net.corda.testing.core.singleIdentity import net.corda.testing.node.internal.* import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatThrownBy import org.junit.After import org.junit.Test +import rx.Observable class FinalityHandlerTest { private val mockNet = InternalMockNetwork() @@ -31,51 +37,115 @@ class FinalityHandlerTest { fun `sent to flow hospital on error and attempted retry on node restart`() { // Setup a network where only Alice has the finance CorDapp and it sends a cash tx to Bob who doesn't have the // CorDapp. Bob's FinalityHandler will error when validating the tx. - val alice = mockNet.createNode(InternalMockNodeParameters(legalName = ALICE_NAME, additionalCordapps = setOf(FINANCE_CORDAPP))) + val alice = mockNet.createNode(InternalMockNodeParameters( + legalName = ALICE_NAME, + additionalCordapps = setOf(FINANCE_CORDAPP) + )) - var bob = mockNet.createNode(InternalMockNodeParameters(legalName = BOB_NAME)) + var bob = mockNet.createNode(InternalMockNodeParameters( + legalName = BOB_NAME, + // The node disables the FinalityHandler completely if there are no old CorDapps loaded, so we need to add + // a token old CorDapp to keep the handler running. + additionalCordapps = setOf(cordappForPackages(javaClass.packageName).withTargetVersion(3)) + )) - val stx = TransactionBuilder(mockNet.defaultNotaryIdentity).let { - Cash().generateIssue( - it, - 1000.POUNDS.issuedBy(alice.info.singleIdentity().ref(0)), - bob.info.singleIdentity(), - mockNet.defaultNotaryIdentity - ) - alice.services.signInitialTransaction(it) + val stx = alice.issueCashTo(bob) + val finalityHandlerId = bob.trackFinalityHandlerId().run { + alice.finaliseWithOldApi(stx) + getOrThrow() } - val finalityHandlerIdFuture = bob.smm.track() - .updates - .filter { it.logic is FinalityHandler } - .map { it.logic.runId } - .toFuture() - - val finalisedTx = alice.services.startFlow(FinalityFlow(stx)).run { - mockNet.runNetwork() - resultFuture.getOrThrow() - } - val finalityHandlerId = finalityHandlerIdFuture.getOrThrow() - - bob.assertFlowSentForObservation(finalityHandlerId) - assertThat(bob.getTransaction(finalisedTx.id)).isNull() + bob.assertFlowSentForObservationDueToConstraintError(finalityHandlerId) + assertThat(bob.getTransaction(stx.id)).isNull() bob = mockNet.restartNode(bob) // Since we've not done anything to fix the orignal error, we expect the finality handler to be sent to the hospital // again on restart - bob.assertFlowSentForObservation(finalityHandlerId) - assertThat(bob.getTransaction(finalisedTx.id)).isNull() + bob.assertFlowSentForObservationDueToConstraintError(finalityHandlerId) + assertThat(bob.getTransaction(stx.id)).isNull() } - private fun TestStartedNode.assertFlowSentForObservation(runId: StateMachineRunId) { - val keptInForObservation = smm.flowHospital - .track() - .let { it.updates.startWith(it.snapshot) } - .ofType(MedicalRecord.Flow::class.java) - .filter { it.flowId == runId && it.outcome == Outcome.OVERNIGHT_OBSERVATION } + @Test + fun `disabled if there are no old CorDapps loaded`() { + val alice = mockNet.createNode(InternalMockNodeParameters( + legalName = ALICE_NAME, + additionalCordapps = setOf(FINANCE_CORDAPP) + )) + + val bob = mockNet.createNode(InternalMockNodeParameters( + legalName = BOB_NAME, + // Make sure the target version is 4, and not the current platform version which may be greater + additionalCordapps = setOf(FINANCE_CORDAPP.withTargetVersion(4)) + )) + + val stx = alice.issueCashTo(bob) + val finalityFuture = alice.finaliseWithOldApi(stx) + + val record = bob.medicalRecordsOfType() .toBlocking() .first() - assertThat(keptInForObservation.by).contains(FinalityDoctor) + assertThat(record.outcome).isEqualTo(Outcome.OVERNIGHT_OBSERVATION) + assertThat(record.sender).isEqualTo(alice.info.singleIdentity()) + assertThat(record.initiatorFlowClassName).isEqualTo(FinalityFlow::class.java.name) + + assertThat(bob.getTransaction(stx.id)).isNull() + + // Drop the session-init so that Alice gets the error message + assertThat(finalityFuture).isNotDone() + bob.smm.flowHospital.dropSessionInit(record.id) + mockNet.runNetwork() + assertThatThrownBy { + finalityFuture.getOrThrow() + }.hasMessageContaining("Counterparty attempting to use the old insecure API of FinalityFlow") + } + + private fun TestStartedNode.issueCashTo(recipient: TestStartedNode): SignedTransaction { + return TransactionBuilder(mockNet.defaultNotaryIdentity).let { + Cash().generateIssue( + it, + 1000.POUNDS.issuedBy(info.singleIdentity().ref(0)), + recipient.info.singleIdentity(), + mockNet.defaultNotaryIdentity + ) + services.signInitialTransaction(it) + } + } + + private fun TestStartedNode.trackFinalityHandlerId(): CordaFuture { + return smm + .track() + .updates + .filter { it.logic is FinalityHandler } + .map { it.logic.runId } + .toFuture() + } + + private fun TestStartedNode.finaliseWithOldApi(stx: SignedTransaction): CordaFuture { + return CordappInfoResolver.withCordappInfo(targetPlatformVersion = 3) { + @Suppress("DEPRECATION") + services.startFlow(FinalityFlow(stx)).resultFuture.apply { + mockNet.runNetwork() + } + } + } + + private inline fun TestStartedNode.medicalRecordsOfType(): Observable { + return smm + .flowHospital + .track() + .let { it.updates.startWith(it.snapshot) } + .ofType(R::class.java) + } + + private fun TestStartedNode.assertFlowSentForObservationDueToConstraintError(runId: StateMachineRunId) { + val observation = medicalRecordsOfType() + .filter { it.flowId == runId } + .toBlocking() + .first() + assertThat(observation.outcome).isEqualTo(Outcome.OVERNIGHT_OBSERVATION) + assertThat(observation.by).contains(FinalityDoctor) + val error = observation.errors.single() + assertThat(error).isInstanceOf(TransactionVerificationException.ContractConstraintRejection::class.java) } private fun TestStartedNode.getTransaction(id: SecureHash): SignedTransaction? { diff --git a/node/src/test/kotlin/net/corda/node/services/ServiceHubConcurrentUsageTest.kt b/node/src/test/kotlin/net/corda/node/services/ServiceHubConcurrentUsageTest.kt index df679fcbb5..68e9a8d02d 100644 --- a/node/src/test/kotlin/net/corda/node/services/ServiceHubConcurrentUsageTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/ServiceHubConcurrentUsageTest.kt @@ -65,7 +65,7 @@ class ServiceHubConcurrentUsageTest { val issuer = ourIdentity.ref(OpaqueBytes.of(0)) Cash().generateIssue(builder, 10.DOLLARS.issuedBy(issuer), ourIdentity, notary) val stx = serviceHub.signInitialTransaction(builder) - return subFlow(FinalityFlow(stx)) + return subFlow(FinalityFlow(stx, emptyList())) } } } diff --git a/node/src/test/kotlin/net/corda/node/services/TimedFlowTests.kt b/node/src/test/kotlin/net/corda/node/services/TimedFlowTests.kt index b8c9425cbb..40b7dcaa21 100644 --- a/node/src/test/kotlin/net/corda/node/services/TimedFlowTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/TimedFlowTests.kt @@ -156,7 +156,7 @@ class TimedFlowTests { setTimeWindow(services.clock.instant(), 30.seconds) addOutputState(DummyContract.SingleOwnerState(owner = info.singleIdentity()), DummyContract.PROGRAM_ID, AlwaysAcceptAttachmentConstraint) } - val flow = FinalityFlow(issueTx) + val flow = FinalityFlow(issueTx, emptyList()) val progressTracker = flow.progressTracker assertNotEquals(ProgressTracker.DONE, progressTracker.currentStep) val progressTrackerDone = getDoneFuture(flow.progressTracker) diff --git a/node/src/test/kotlin/net/corda/node/services/events/ScheduledFlowTests.kt b/node/src/test/kotlin/net/corda/node/services/events/ScheduledFlowTests.kt index eeb2f0582e..4ce505abbd 100644 --- a/node/src/test/kotlin/net/corda/node/services/events/ScheduledFlowTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/events/ScheduledFlowTests.kt @@ -4,11 +4,9 @@ import co.paralleluniverse.fibers.Suspendable import net.corda.core.concurrent.CordaFuture import net.corda.core.context.InvocationOrigin import net.corda.core.contracts.* -import net.corda.core.flows.FinalityFlow -import net.corda.core.flows.FlowLogic -import net.corda.core.flows.FlowLogicRefFactory -import net.corda.core.flows.SchedulableFlow +import net.corda.core.flows.* import net.corda.core.identity.Party +import net.corda.core.internal.packageName import net.corda.core.node.services.VaultService import net.corda.core.node.services.queryBy import net.corda.core.node.services.vault.QueryCriteria.VaultQueryCriteria @@ -60,6 +58,7 @@ class ScheduledFlowTests { override val participants: List get() = listOf(source, destination) } + @InitiatingFlow class InsertInitialStateFlow(private val destination: Party, private val notary: Party) : FlowLogic() { @Suspendable override fun call() { @@ -68,10 +67,19 @@ class ScheduledFlowTests { .addOutputState(scheduledState, DummyContract.PROGRAM_ID) .addCommand(dummyCommand(ourIdentity.owningKey)) val tx = serviceHub.signInitialTransaction(builder) - subFlow(FinalityFlow(tx)) + subFlow(FinalityFlow(tx, initiateFlow(destination))) } } + @InitiatedBy(InsertInitialStateFlow::class) + class InsertInitialStateResponderFlow(private val otherSide: FlowSession) : FlowLogic() { + @Suspendable + override fun call() { + subFlow(ReceiveFinalityFlow(otherSide)) + } + } + + @InitiatingFlow @SchedulableFlow class ScheduledFlow(private val stateRef: StateRef) : FlowLogic() { @Suspendable @@ -90,13 +98,21 @@ class ScheduledFlowTests { .addOutputState(newStateOutput, DummyContract.PROGRAM_ID) .addCommand(dummyCommand(ourIdentity.owningKey)) val tx = serviceHub.signInitialTransaction(builder) - subFlow(FinalityFlow(tx, setOf(scheduledState.destination))) + subFlow(FinalityFlow(tx, initiateFlow(scheduledState.destination))) + } + } + + @InitiatedBy(ScheduledFlow::class) + class ScheduledResponderFlow(private val otherSide: FlowSession) : FlowLogic() { + @Suspendable + override fun call() { + subFlow(ReceiveFinalityFlow(otherSide)) } } @Before fun setup() { - mockNet = InternalMockNetwork(cordappsForAllNodes = cordappsForPackages("net.corda.testing.contracts"), threadPerNode = true) + mockNet = InternalMockNetwork(cordappsForAllNodes = cordappsForPackages("net.corda.testing.contracts", javaClass.packageName), threadPerNode = true) aliceNode = mockNet.createNode(InternalMockNodeParameters(legalName = ALICE_NAME)) bobNode = mockNet.createNode(InternalMockNodeParameters(legalName = BOB_NAME)) notary = mockNet.defaultNotaryIdentity diff --git a/node/src/test/kotlin/net/corda/node/services/statemachine/FlowFrameworkTests.kt b/node/src/test/kotlin/net/corda/node/services/statemachine/FlowFrameworkTests.kt index 23b919eb66..fb39bfe873 100644 --- a/node/src/test/kotlin/net/corda/node/services/statemachine/FlowFrameworkTests.kt +++ b/node/src/test/kotlin/net/corda/node/services/statemachine/FlowFrameworkTests.kt @@ -7,14 +7,11 @@ import co.paralleluniverse.strands.concurrent.Semaphore import net.corda.client.rpc.notUsed import net.corda.core.concurrent.CordaFuture import net.corda.core.contracts.ContractState -import net.corda.core.contracts.StateAndRef +import net.corda.core.crypto.SecureHash import net.corda.core.crypto.random63BitValue import net.corda.core.flows.* import net.corda.core.identity.Party -import net.corda.core.internal.FlowStateMachine import net.corda.core.internal.concurrent.flatMap -import net.corda.core.internal.concurrent.map -import net.corda.core.internal.uncheckedCast import net.corda.core.messaging.MessageRecipients import net.corda.core.node.services.PartyInfo import net.corda.core.node.services.queryBy @@ -30,7 +27,10 @@ import net.corda.core.utilities.unwrap import net.corda.node.services.persistence.checkpoints import net.corda.testing.contracts.DummyContract import net.corda.testing.contracts.DummyState -import net.corda.testing.core.* +import net.corda.testing.core.ALICE_NAME +import net.corda.testing.core.BOB_NAME +import net.corda.testing.core.dummyCommand +import net.corda.testing.core.singleIdentity import net.corda.testing.internal.LogHelper import net.corda.testing.node.InMemoryMessagingNetwork.MessageTransfer import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin @@ -66,7 +66,7 @@ class FlowFrameworkTests { @Before fun setUpMockNet() { mockNet = InternalMockNetwork( - cordappsForAllNodes = cordappsForPackages("net.corda.testing.contracts"), + cordappsForAllNodes = cordappsForPackages("net.corda.testing.contracts") + FINANCE_CORDAPP, servicePeerAllocationStrategy = RoundRobin() ) @@ -266,18 +266,20 @@ class FlowFrameworkTests { } @Test - fun `wait for transaction`() { + fun waitForLedgerCommit() { val ptx = TransactionBuilder(notary = notaryIdentity) .addOutputState(DummyState(), DummyContract.PROGRAM_ID) .addCommand(dummyCommand(alice.owningKey)) val stx = aliceNode.services.signInitialTransaction(ptx) - val committerFiber = aliceNode.registerCordappFlowFactory(WaitingFlows.Waiter::class) { - WaitingFlows.Committer(it) - }.map { it.stateMachine }.map { uncheckedCast, FlowStateMachine>(it) } - val waiterStx = bobNode.services.startFlow(WaitingFlows.Waiter(stx, alice)).resultFuture + val committerStx = aliceNode.registerCordappFlowFactory(CommitReceiverFlow::class) { + CommitterFlow(it) + }.flatMap { it.stateMachine.resultFuture } + // The waitForLedgerCommit call has to occur on separate flow + val waiterStx = bobNode.services.startFlow(WaiterFlow(stx.id)).resultFuture + val commitReceiverStx = bobNode.services.startFlow(CommitReceiverFlow(stx, alice)).resultFuture mockNet.runNetwork() - assertThat(waiterStx.getOrThrow()).isEqualTo(committerFiber.getOrThrow().resultFuture.getOrThrow()) + assertThat(committerStx.getOrThrow()).isEqualTo(waiterStx.getOrThrow()).isEqualTo(commitReceiverStx.getOrThrow()) } @Test @@ -287,10 +289,8 @@ class FlowFrameworkTests { .addCommand(dummyCommand()) val stx = aliceNode.services.signInitialTransaction(ptx) - aliceNode.registerCordappFlowFactory(WaitingFlows.Waiter::class) { - WaitingFlows.Committer(it) { throw Exception("Error") } - } - val waiter = bobNode.services.startFlow(WaitingFlows.Waiter(stx, alice)).resultFuture + aliceNode.registerCordappFlowFactory(CommitReceiverFlow::class) { CommitterFlow(it) { throw Exception("Error") } } + val waiter = bobNode.services.startFlow(CommitReceiverFlow(stx, alice)).resultFuture mockNet.runNetwork() assertThatExceptionOfType(UnexpectedFlowEndException::class.java).isThrownBy { waiter.getOrThrow() @@ -299,18 +299,10 @@ class FlowFrameworkTests { @Test fun `verify vault query service is tokenizable by force checkpointing within a flow`() { - val ptx = TransactionBuilder(notary = notaryIdentity) - .addOutputState(DummyState(), DummyContract.PROGRAM_ID) - .addCommand(dummyCommand(alice.owningKey)) - val stx = aliceNode.services.signInitialTransaction(ptx) - - aliceNode.registerCordappFlowFactory(VaultQueryFlow::class) { - WaitingFlows.Committer(it) - } - val result = bobNode.services.startFlow(VaultQueryFlow(stx, alice)).resultFuture - + aliceNode.registerCordappFlowFactory(VaultQueryFlow::class) { InitiatedSendFlow("Hello", it) } + val result = bobNode.services.startFlow(VaultQueryFlow(alice)).resultFuture mockNet.runNetwork() - assertThat(result.getOrThrow()).isEmpty() + result.getOrThrow() } @Test @@ -492,24 +484,27 @@ class FlowFrameworkTests { } } - private object WaitingFlows { - @InitiatingFlow - class Waiter(val stx: SignedTransaction, val otherParty: Party) : FlowLogic() { - @Suspendable - override fun call(): SignedTransaction { - val otherPartySession = initiateFlow(otherParty) - otherPartySession.send(stx) - return waitForLedgerCommit(stx.id) - } - } + class WaiterFlow(private val txId: SecureHash) : FlowLogic() { + @Suspendable + override fun call(): SignedTransaction = waitForLedgerCommit(txId) + } - class Committer(val otherPartySession: FlowSession, val throwException: (() -> Exception)? = null) : FlowLogic() { - @Suspendable - override fun call(): SignedTransaction { - val stx = otherPartySession.receive().unwrap { it } - if (throwException != null) throw throwException.invoke() - return subFlow(FinalityFlow(stx, setOf(otherPartySession.counterparty))) - } + @InitiatingFlow + class CommitReceiverFlow(val stx: SignedTransaction, private val otherParty: Party) : FlowLogic() { + @Suspendable + override fun call(): SignedTransaction { + val otherPartySession = initiateFlow(otherParty) + otherPartySession.send(stx) + return subFlow(ReceiveFinalityFlow(otherPartySession, expectedTxId = stx.id)) + } + } + + class CommitterFlow(private val otherPartySession: FlowSession, private val throwException: (() -> Exception)? = null) : FlowLogic() { + @Suspendable + override fun call(): SignedTransaction { + val stx = otherPartySession.receive().unwrap { it } + if (throwException != null) throw throwException.invoke() + return subFlow(FinalityFlow(stx, otherPartySession)) } } @@ -527,16 +522,15 @@ class FlowFrameworkTests { private class IncorrectCustomSendFlow(payload: String, otherParty: Party) : CustomInterface, SendFlow(payload, otherParty) @InitiatingFlow - private class VaultQueryFlow(val stx: SignedTransaction, val otherParty: Party) : FlowLogic>>() { + private class VaultQueryFlow(val otherParty: Party) : FlowLogic() { @Suspendable - override fun call(): List> { + override fun call() { val otherPartySession = initiateFlow(otherParty) - otherPartySession.send(stx) - // hold onto reference here to force checkpoint of vaultService and thus + // Hold onto reference here to force checkpoint of vaultService and thus // prove it is registered as a tokenizableService in the node val vaultQuerySvc = serviceHub.vaultService - waitForLedgerCommit(stx.id) - return vaultQuerySvc.queryBy().states + otherPartySession.receive() + vaultQuerySvc.queryBy().states } } diff --git a/node/src/test/kotlin/net/corda/node/services/vault/VaultFlowTest.kt b/node/src/test/kotlin/net/corda/node/services/vault/VaultFlowTest.kt index ea1a78704c..23359b1cfd 100644 --- a/node/src/test/kotlin/net/corda/node/services/vault/VaultFlowTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/vault/VaultFlowTest.kt @@ -1,9 +1,7 @@ package net.corda.node.services.vault import co.paralleluniverse.fibers.Suspendable -import net.corda.core.flows.FinalityFlow -import net.corda.core.flows.FlowLogic -import net.corda.core.flows.InitiatingFlow +import net.corda.core.flows.* import net.corda.core.identity.CordaX500Name import net.corda.core.identity.Party import net.corda.core.node.services.queryBy @@ -26,7 +24,6 @@ import java.util.concurrent.ExecutionException import kotlin.test.assertEquals class VaultFlowTest { - private lateinit var mockNetwork: MockNetwork private lateinit var partyA: StartedMockNode private lateinit var partyB: StartedMockNode @@ -72,17 +69,26 @@ class VaultFlowTest { partyB.services.vaultService.queryBy().states.size }) } -} -@InitiatingFlow -class Initiator(private val participants: List) : FlowLogic() { - @Suspendable - override fun call() { - val stx = serviceHub.signInitialTransaction(TransactionBuilder(serviceHub.networkMapCache.notaryIdentities.first()).apply { - addOutputState(UniqueDummyLinearContract.State(participants, "Dummy linear id"), UNIQUE_DUMMY_LINEAR_CONTRACT_PROGRAM_ID) - addOutputState(DummyDealContract.State(participants, "linear id"), DUMMY_DEAL_PROGRAM_ID) - addCommand(DummyCommandData, listOf(ourIdentity.owningKey)) - }) - subFlow(FinalityFlow(stx)) + @InitiatingFlow + class Initiator(private val participants: List) : FlowLogic() { + @Suspendable + override fun call() { + val stx = serviceHub.signInitialTransaction(TransactionBuilder(serviceHub.networkMapCache.notaryIdentities.first()).apply { + addOutputState(UniqueDummyLinearContract.State(participants, "Dummy linear id"), UNIQUE_DUMMY_LINEAR_CONTRACT_PROGRAM_ID) + addOutputState(DummyDealContract.State(participants, "linear id"), DUMMY_DEAL_PROGRAM_ID) + addCommand(DummyCommandData, listOf(ourIdentity.owningKey)) + }) + val sessions = participants.mapNotNull { if (it != ourIdentity) initiateFlow(it) else null } + subFlow(FinalityFlow(stx, sessions)) + } + } + + @InitiatedBy(Initiator::class) + class Responder(private val otherSide: FlowSession) : FlowLogic() { + @Suspendable + override fun call() { + subFlow(ReceiveFinalityFlow(otherSide)) + } } } diff --git a/node/src/test/kotlin/net/corda/node/services/vault/VaultSoftLockManagerTest.kt b/node/src/test/kotlin/net/corda/node/services/vault/VaultSoftLockManagerTest.kt index 2bbe01d5a8..7cd8fd3b39 100644 --- a/node/src/test/kotlin/net/corda/node/services/vault/VaultSoftLockManagerTest.kt +++ b/node/src/test/kotlin/net/corda/node/services/vault/VaultSoftLockManagerTest.kt @@ -101,12 +101,13 @@ class VaultSoftLockManagerTest { object CommandDataImpl : CommandData class ClientLogic(nodePair: NodePair, val state: ContractState) : NodePair.AbstractClientLogic>(nodePair) { - override fun callImpl() = run { - subFlow(FinalityFlow(serviceHub.signInitialTransaction(TransactionBuilder(notary = ourIdentity).apply { + override fun callImpl(): List { + val stx = serviceHub.signInitialTransaction(TransactionBuilder(notary = ourIdentity).apply { addOutputState(state, ContractImpl::class.jvmName) addCommand(CommandDataImpl, ourIdentity.owningKey) - }))) - serviceHub.vaultService.queryBy(VaultQueryCriteria(softLockingCondition = SoftLockingCondition(LOCKED_ONLY))).states.map { + }) + subFlow(FinalityFlow(stx, emptyList())) + return serviceHub.vaultService.queryBy(VaultQueryCriteria(softLockingCondition = SoftLockingCondition(LOCKED_ONLY))).states.map { it.state.data } } diff --git a/perftestcordapp/build.gradle b/perftestcordapp/build.gradle index 8e06707fc6..6581ed70e5 100644 --- a/perftestcordapp/build.gradle +++ b/perftestcordapp/build.gradle @@ -72,7 +72,9 @@ cordapp { info { name "net/corda/perftestcordapp" vendor "R3" - targetPlatformVersion corda_platform_version.toInteger() + // TODO Update the performance test cordapp to use the new FinalityFlow API +// targetPlatformVersion corda_platform_version.toInteger() + targetPlatformVersion 3 minimumPlatformVersion 1 } } diff --git a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/asset/CashSelectionH2Test.kt b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/asset/CashSelectionH2Test.kt index 9114b06343..5a78d0c714 100644 --- a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/asset/CashSelectionH2Test.kt +++ b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/contracts/asset/CashSelectionH2Test.kt @@ -11,6 +11,7 @@ import net.corda.core.utilities.getOrThrow import net.corda.testing.node.MockNetwork import net.corda.testing.node.MockNodeConfigOverrides import net.corda.testing.node.MockNodeParameters +import net.corda.testing.node.internal.cordappForPackages import org.assertj.core.api.Assertions.assertThatThrownBy import org.junit.After import org.junit.Test @@ -19,7 +20,10 @@ import java.util.Collections.nCopies class CashSelectionH2Test { private val mockNet = MockNetwork( threadPerNode = true, - cordappPackages = listOf("com.r3.corda.enterprise.perftestcordapp.contracts.asset", "com.r3.corda.enterprise.perftestcordapp.schemas")) + cordappPackages = emptyList(), + // TODO Update the performance test cordapp to use the new FinalityFlow API + cordappsForAllNodes = listOf(cordappForPackages("com.r3.corda.enterprise.perftestcordapp").withTargetVersion(3)) + ) @After fun cleanUp() { diff --git a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashExitFlowTests.kt b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashExitFlowTests.kt index 10f2e93cc8..641bc79047 100644 --- a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashExitFlowTests.kt +++ b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashExitFlowTests.kt @@ -10,6 +10,7 @@ import net.corda.testing.core.BOC_NAME import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin import net.corda.testing.node.MockNetwork import net.corda.testing.node.StartedMockNode +import net.corda.testing.node.internal.cordappForPackages import org.junit.After import org.junit.Before import org.junit.Test @@ -26,8 +27,12 @@ class CashExitFlowTests { @Before fun start() { - mockNet = MockNetwork(servicePeerAllocationStrategy = RoundRobin(), - cordappPackages = listOf("com.r3.corda.enterprise.perftestcordapp.contracts.asset", "com.r3.corda.enterprise.perftestcordapp.schemas")) + mockNet = MockNetwork( + servicePeerAllocationStrategy = RoundRobin(), + cordappPackages = emptyList(), + // TODO Update the performance test cordapp to use the new FinalityFlow API + cordappsForAllNodes = listOf(cordappForPackages("com.r3.corda.enterprise.perftestcordapp").withTargetVersion(3)) + ) bankOfCordaNode = mockNet.createPartyNode(BOC_NAME) bankOfCorda = bankOfCordaNode.info.identityFromX500Name(BOC_NAME) notary = mockNet.defaultNotaryIdentity diff --git a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashIssueAndPaymentFlowTests.kt b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashIssueAndPaymentFlowTests.kt index 0e8c7f4cb5..c47d274a36 100644 --- a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashIssueAndPaymentFlowTests.kt +++ b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashIssueAndPaymentFlowTests.kt @@ -11,10 +11,7 @@ import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.getOrThrow import net.corda.testing.core.* import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin -import net.corda.testing.node.internal.InternalMockNetwork -import net.corda.testing.node.internal.TestStartedNode -import net.corda.testing.node.internal.cordappsForPackages -import net.corda.testing.node.internal.startFlow +import net.corda.testing.node.internal.* import org.junit.After import org.junit.Before import org.junit.Test @@ -30,8 +27,11 @@ class CashIssueAndPaymentFlowTests { @Before fun start() { - mockNet = InternalMockNetwork(servicePeerAllocationStrategy = RoundRobin(), - cordappsForAllNodes = cordappsForPackages("com.r3.corda.enterprise.perftestcordapp.contracts.asset", "com.r3.corda.enterprise.perftestcordapp.schemas")) + mockNet = InternalMockNetwork( + servicePeerAllocationStrategy = RoundRobin(), + // TODO Update the performance test cordapp to use the new FinalityFlow API + cordappsForAllNodes = listOf(cordappForPackages("com.r3.corda.enterprise.perftestcordapp").withTargetVersion(3)) + ) bankOfCordaNode = mockNet.createPartyNode(BOC_NAME) aliceNode = mockNet.createPartyNode(ALICE_NAME) bankOfCorda = bankOfCordaNode.info.singleIdentity() diff --git a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashIssueAndPaymentNoSelectionFlowTest.kt b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashIssueAndPaymentNoSelectionFlowTests.kt similarity index 87% rename from perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashIssueAndPaymentNoSelectionFlowTest.kt rename to perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashIssueAndPaymentNoSelectionFlowTests.kt index 69d76eb679..3cc5786639 100644 --- a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashIssueAndPaymentNoSelectionFlowTest.kt +++ b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashIssueAndPaymentNoSelectionFlowTests.kt @@ -11,10 +11,7 @@ import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.getOrThrow import net.corda.testing.core.* import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin -import net.corda.testing.node.internal.InternalMockNetwork -import net.corda.testing.node.internal.TestStartedNode -import net.corda.testing.node.internal.cordappsForPackages -import net.corda.testing.node.internal.startFlow +import net.corda.testing.node.internal.* import org.junit.After import org.junit.Before import org.junit.Test @@ -23,7 +20,7 @@ import org.junit.runners.Parameterized import kotlin.test.assertEquals @RunWith(Parameterized::class) -class CashIssueAndPayNoSelectionTests(private val anonymous: Boolean) { +class CashIssueAndPaymentNoSelectionTests(private val anonymous: Boolean) { companion object { @Parameterized.Parameters(name = "Anonymous = {0}") @JvmStatic @@ -39,8 +36,11 @@ class CashIssueAndPayNoSelectionTests(private val anonymous: Boolean) { @Before fun start() { - mockNet = InternalMockNetwork(servicePeerAllocationStrategy = RoundRobin(), - cordappsForAllNodes = cordappsForPackages("com.r3.corda.enterprise.perftestcordapp.contracts.asset", "com.r3.corda.enterprise.perftestcordapp.schemas")) + mockNet = InternalMockNetwork( + servicePeerAllocationStrategy = RoundRobin(), + // TODO Update the performance test cordapp to use the new FinalityFlow API + cordappsForAllNodes = listOf(cordappForPackages("com.r3.corda.enterprise.perftestcordapp").withTargetVersion(3)) + ) bankOfCordaNode = mockNet.createPartyNode(BOC_NAME) aliceNode = mockNet.createPartyNode(ALICE_NAME) bankOfCorda = bankOfCordaNode.info.singleIdentity() diff --git a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashIssueFlowTests.kt b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashIssueFlowTests.kt index be5d4f641c..7d2cf5ebc5 100644 --- a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashIssueFlowTests.kt +++ b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashIssueFlowTests.kt @@ -10,6 +10,7 @@ import net.corda.testing.core.BOC_NAME import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin import net.corda.testing.node.MockNetwork import net.corda.testing.node.StartedMockNode +import net.corda.testing.node.internal.cordappForPackages import org.junit.After import org.junit.Before import org.junit.Test @@ -26,7 +27,10 @@ class CashIssueFlowTests { fun start() { mockNet = MockNetwork( servicePeerAllocationStrategy = RoundRobin(), - cordappPackages = listOf("com.r3.corda.enterprise.perftestcordapp.contracts.asset", "com.r3.corda.enterprise.perftestcordapp.schemas")) + cordappPackages = emptyList(), + // TODO Update the performance test cordapp to use the new FinalityFlow API + cordappsForAllNodes = listOf(cordappForPackages("com.r3.corda.enterprise.perftestcordapp").withTargetVersion(3)) + ) bankOfCordaNode = mockNet.createPartyNode(BOC_NAME) bankOfCorda = bankOfCordaNode.info.identityFromX500Name(BOC_NAME) notary = mockNet.defaultNotaryIdentity diff --git a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashPaymentFlowTests.kt b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashPaymentFlowTests.kt index fe55b747b1..edc75850d4 100644 --- a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashPaymentFlowTests.kt +++ b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/CashPaymentFlowTests.kt @@ -11,10 +11,7 @@ import net.corda.core.utilities.OpaqueBytes import net.corda.core.utilities.getOrThrow import net.corda.testing.core.* import net.corda.testing.node.InMemoryMessagingNetwork.ServicePeerAllocationStrategy.RoundRobin -import net.corda.testing.node.internal.InternalMockNetwork -import net.corda.testing.node.internal.TestStartedNode -import net.corda.testing.node.internal.cordappsForPackages -import net.corda.testing.node.internal.startFlow +import net.corda.testing.node.internal.* import org.junit.After import org.junit.Before import org.junit.Test @@ -33,7 +30,9 @@ class CashPaymentFlowTests { fun start() { mockNet = InternalMockNetwork( servicePeerAllocationStrategy = RoundRobin(), - cordappsForAllNodes = cordappsForPackages("com.r3.corda.enterprise.perftestcordapp.contracts.asset", "com.r3.corda.enterprise.perftestcordapp.schemas")) + // TODO Update the performance test cordapp to use the new FinalityFlow API + cordappsForAllNodes = listOf(cordappForPackages("com.r3.corda.enterprise.perftestcordapp").withTargetVersion(3)) + ) bankOfCordaNode = mockNet.createPartyNode(BOC_NAME) aliceNode = mockNet.createPartyNode(ALICE_NAME) bankOfCorda = bankOfCordaNode.info.singleIdentity() diff --git a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/TwoPartyTradeFlowTest.kt b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/TwoPartyTradeFlowTests.kt similarity index 97% rename from perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/TwoPartyTradeFlowTest.kt rename to perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/TwoPartyTradeFlowTests.kt index 2c4ad21697..80086b82e7 100644 --- a/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/TwoPartyTradeFlowTest.kt +++ b/perftestcordapp/src/test/kotlin/com/r3/corda/enterprise/perftestcordapp/flows/TwoPartyTradeFlowTests.kt @@ -52,7 +52,6 @@ import net.corda.testing.dsl.TestTransactionDSLInterpreter import net.corda.testing.internal.LogHelper import net.corda.testing.internal.TEST_TX_TIME import net.corda.testing.internal.rigorousMock -import net.corda.testing.node.MockServices import net.corda.testing.node.internal.* import net.corda.testing.node.ledger import org.assertj.core.api.Assertions.assertThat @@ -86,14 +85,13 @@ internal fun CheckpointStorage.checkpoints(): List> @RunWith(Parameterized::class) class TwoPartyTradeFlowTests(private val anonymous: Boolean) { companion object { - private val cordappPackages = listOf("com.r3.corda.enterprise.perftestcordapp.contracts", "com.r3.corda.enterprise.perftestcordapp.schemas") - private val cordappsForAllNodes = cordappsForPackages(cordappPackages) + // TODO Update the performance test cordapp to use the new FinalityFlow API + private val cordappsForAllNodes = listOf(cordappForPackages("com.r3.corda.enterprise.perftestcordapp").withTargetVersion(3)) @JvmStatic @Parameterized.Parameters(name = "Anonymous = {0}") fun data(): Collection = listOf(true, false) private val dummyNotary = TestIdentity(DUMMY_NOTARY_NAME, 20) - private val MEGA_CORP = TestIdentity(CordaX500Name("MegaCorp", "London", "GB")).party private val DUMMY_NOTARY get() = dummyNotary.party } @@ -117,7 +115,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) { // allow interruption half way through. mockNet = InternalMockNetwork(threadPerNode = true, cordappsForAllNodes = cordappsForAllNodes) val ledgerIdentityService = rigorousMock() - MockServices(cordappPackages, MEGA_CORP.name, ledgerIdentityService).ledger(DUMMY_NOTARY) { + mockNet.defaultNotaryNode.services.ledger(DUMMY_NOTARY) { val notaryNode = mockNet.defaultNotaryNode val aliceNode = mockNet.createPartyNode(ALICE_NAME) val bobNode = mockNet.createPartyNode(BOB_NAME) @@ -170,7 +168,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) { fun `trade cash for commercial paper fails using soft locking`() { mockNet = InternalMockNetwork(threadPerNode = true, cordappsForAllNodes = cordappsForAllNodes) val ledgerIdentityService = rigorousMock() - MockServices(cordappPackages, MEGA_CORP.name, ledgerIdentityService).ledger(DUMMY_NOTARY) { + mockNet.defaultNotaryNode.services.ledger(DUMMY_NOTARY) { val notaryNode = mockNet.defaultNotaryNode val aliceNode = mockNet.createPartyNode(ALICE_NAME) val bobNode = mockNet.createPartyNode(BOB_NAME) @@ -228,7 +226,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) { fun `shutdown and restore`() { mockNet = InternalMockNetwork(cordappsForAllNodes = cordappsForAllNodes) val ledgerIdentityService = rigorousMock() - MockServices(cordappPackages, MEGA_CORP.name, ledgerIdentityService).ledger(DUMMY_NOTARY) { + mockNet.defaultNotaryNode.services.ledger(DUMMY_NOTARY) { val notaryNode = mockNet.defaultNotaryNode val aliceNode = mockNet.createPartyNode(ALICE_NAME) var bobNode = mockNet.createPartyNode(BOB_NAME) @@ -523,7 +521,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) { fun `dependency with error on buyer side`() { mockNet = InternalMockNetwork(cordappsForAllNodes = cordappsForAllNodes) val ledgerIdentityService = rigorousMock() - MockServices(cordappPackages, MEGA_CORP.name, ledgerIdentityService).ledger(DUMMY_NOTARY) { + mockNet.defaultNotaryNode.services.ledger(DUMMY_NOTARY) { runWithError(ledgerIdentityService, true, false, "at least one cash input") } } @@ -532,7 +530,7 @@ class TwoPartyTradeFlowTests(private val anonymous: Boolean) { fun `dependency with error on seller side`() { mockNet = InternalMockNetwork(cordappsForAllNodes = cordappsForAllNodes) val ledgerIdentityService = rigorousMock() - MockServices(cordappPackages, MEGA_CORP.name, ledgerIdentityService).ledger(DUMMY_NOTARY) { + mockNet.defaultNotaryNode.services.ledger(DUMMY_NOTARY) { runWithError(ledgerIdentityService, false, true, "Issuances have a time-window") } } diff --git a/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/AttachmentDemo.kt b/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/AttachmentDemo.kt index 9ff022f1b6..08a4fa3873 100644 --- a/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/AttachmentDemo.kt +++ b/samples/attachment-demo/src/main/kotlin/net/corda/attachmentdemo/AttachmentDemo.kt @@ -8,16 +8,14 @@ import net.corda.core.contracts.Contract import net.corda.core.contracts.ContractState import net.corda.core.contracts.TypeOnlyCommandData import net.corda.core.crypto.SecureHash -import net.corda.core.flows.FinalityFlow -import net.corda.core.flows.FlowLogic -import net.corda.core.flows.StartableByRPC -import net.corda.core.flows.StartableByService +import net.corda.core.flows.* import net.corda.core.identity.AbstractParty import net.corda.core.identity.Party import net.corda.core.internal.Emoji import net.corda.core.internal.InputStreamAndHash import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.startTrackedFlow +import net.corda.core.node.StatesToRecord import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder @@ -106,6 +104,7 @@ private fun sender(rpc: CordaRPCOps, inputStream: InputStream, hash: SecureHash. } // DOCEND 2 +@InitiatingFlow @StartableByRPC class AttachmentDemoFlow(private val otherSide: Party, private val notary: Party, @@ -125,10 +124,19 @@ class AttachmentDemoFlow(private val otherSide: Party, progressTracker.currentStep = SIGNING - // Send the transaction to the other recipient val stx = serviceHub.signInitialTransaction(ptx) - return subFlow(FinalityFlow(stx, setOf(otherSide))) + // Send the transaction to the other recipient + return subFlow(FinalityFlow(stx, initiateFlow(otherSide))) + } +} + +@InitiatedBy(AttachmentDemoFlow::class) +class StoreAttachmentFlow(private val otherSide: FlowSession) : FlowLogic() { + @Suspendable + override fun call() { + // As a non-participant to the transaction we need to record all states + subFlow(ReceiveFinalityFlow(otherSide, statesToRecord = StatesToRecord.ALL_VISIBLE)) } } diff --git a/samples/network-verifier/src/main/kotlin/net/corda/verification/TestCommsFlow.kt b/samples/network-verifier/src/main/kotlin/net/corda/verification/TestCommsFlow.kt index 55a3f66109..bce083949e 100644 --- a/samples/network-verifier/src/main/kotlin/net/corda/verification/TestCommsFlow.kt +++ b/samples/network-verifier/src/main/kotlin/net/corda/verification/TestCommsFlow.kt @@ -44,7 +44,7 @@ class TestCommsFlowInitiator(private val x500Name: CordaX500Name? = null) : Flow tx.addOutputState(CommsTestState(responses, serviceHub.myInfo.legalIdentities.first()), CommsTestContract::class.java.name) tx.addCommand(CommsTestCommand, serviceHub.myInfo.legalIdentities.first().owningKey) val signedTx = serviceHub.signInitialTransaction(tx) - subFlow(FinalityFlow(signedTx)) + subFlow(FinalityFlow(signedTx, emptyList())) return responses } diff --git a/samples/network-verifier/src/main/kotlin/net/corda/verification/TestNotaryFlow.kt b/samples/network-verifier/src/main/kotlin/net/corda/verification/TestNotaryFlow.kt index febc4fcfce..8cb5526be4 100644 --- a/samples/network-verifier/src/main/kotlin/net/corda/verification/TestNotaryFlow.kt +++ b/samples/network-verifier/src/main/kotlin/net/corda/verification/TestNotaryFlow.kt @@ -32,14 +32,14 @@ class TestNotaryFlow : FlowLogic() { issueBuilder.addOutputState(NotaryTestState(notary.name.toString(), myIdentity), NotaryTestContract::class.java.name) issueBuilder.addCommand(NotaryTestCommand, myIdentity.owningKey) val signedTx = serviceHub.signInitialTransaction(issueBuilder) - val issueResult = subFlow(FinalityFlow(signedTx)) + val issueResult = subFlow(FinalityFlow(signedTx, emptyList())) progressTracker.currentStep = ISSUED val destroyBuilder = TransactionBuilder() destroyBuilder.notary = notary destroyBuilder.addInputState(issueResult.tx.outRefsOfType().first()) destroyBuilder.addCommand(NotaryTestCommand, myIdentity.owningKey) val signedDestroyT = serviceHub.signInitialTransaction(destroyBuilder) - val result = subFlow(FinalityFlow(signedDestroyT)) + val result = subFlow(FinalityFlow(signedDestroyT, emptyList())) progressTracker.currentStep = DESTROYING progressTracker.currentStep = FINALIZED return "notarised: ${result.notary}::${result.tx.id}" diff --git a/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/flow/CommercialPaperIssueFlow.kt b/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/flow/CommercialPaperIssueFlow.kt index 847e48e8b2..e8a461bf50 100644 --- a/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/flow/CommercialPaperIssueFlow.kt +++ b/samples/trader-demo/src/main/kotlin/net/corda/traderdemo/flow/CommercialPaperIssueFlow.kt @@ -3,9 +3,7 @@ package net.corda.traderdemo.flow import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.Amount import net.corda.core.crypto.SecureHash -import net.corda.core.flows.FinalityFlow -import net.corda.core.flows.FlowLogic -import net.corda.core.flows.StartableByRPC +import net.corda.core.flows.* import net.corda.core.identity.Party import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder @@ -22,6 +20,7 @@ import java.util.* * Flow for the Bank of Corda node to issue some commercial paper to the seller's node, to sell to the buyer. */ @StartableByRPC +@InitiatingFlow class CommercialPaperIssueFlow(private val amount: Amount, private val issueRef: OpaqueBytes, private val recipient: Party, @@ -56,7 +55,7 @@ class CommercialPaperIssueFlow(private val amount: Amount, // Sign it as ourselves. val stx = serviceHub.signInitialTransaction(tx) - subFlow(FinalityFlow(stx)) + subFlow(FinalityFlow(stx, emptyList())) } // Now make a dummy transaction that moves it to a new key, just to show that resolving dependencies works. @@ -65,7 +64,17 @@ class CommercialPaperIssueFlow(private val amount: Amount, val builder = TransactionBuilder(notary) CommercialPaper().generateMove(builder, issuance.tx.outRef(0), recipient) val stx = serviceHub.signInitialTransaction(builder) - subFlow(FinalityFlow(stx)) + val recipientSession = initiateFlow(recipient) + subFlow(FinalityFlow(stx, listOf(recipientSession))) } } } + +@InitiatedBy(CommercialPaperIssueFlow::class) +class CommercialPaperIssueResponderFlow(private val otherSideSession: FlowSession) : FlowLogic() { + @Suspendable + override fun call() { + // Record the move transaction + subFlow(ReceiveFinalityFlow(otherSideSession)) + } +} diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/driver/Driver.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/driver/Driver.kt index dea3e7b33b..476553b94f 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/driver/Driver.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/driver/Driver.kt @@ -588,7 +588,7 @@ data class DriverParameters( fun withNetworkParameters(networkParameters: NetworkParameters): DriverParameters = copy(networkParameters = networkParameters) fun withNotaryCustomOverrides(notaryCustomOverrides: Map): DriverParameters = copy(notaryCustomOverrides = notaryCustomOverrides) fun withInMemoryDB(inMemoryDB: Boolean): DriverParameters = copy(inMemoryDB = inMemoryDB) - fun withCordappsForAllNodes(cordappsForAllNodes: Set?): DriverParameters = copy(cordappsForAllNodes = cordappsForAllNodes) + fun withCordappsForAllNodes(cordappsForAllNodes: Collection?): DriverParameters = copy(cordappsForAllNodes = cordappsForAllNodes) fun copy( isDebug: Boolean, diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/TestCordapp.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/TestCordapp.kt index fed1f14e22..5b1fc6580e 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/TestCordapp.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/TestCordapp.kt @@ -10,7 +10,7 @@ import net.corda.testing.node.internal.simplifyScanPackages */ @DoNotImplement interface TestCordapp { - /** Returns the name, defaults to "test-cordapp" if not specified. */ + /** Returns the name, defaults to "test-name" if not specified. */ val name: String /** Returns the title, defaults to "test-title" if not specified. */ @@ -51,17 +51,21 @@ interface TestCordapp { class Factory { companion object { + /** + * Create a [TestCordapp] object by scanning the given packages. The meta data on the CorDapp will be the + * default values, which can be changed with the wither methods. + */ @JvmStatic fun fromPackages(vararg packageNames: String): TestCordapp = fromPackages(packageNames.asList()) /** * Create a [TestCordapp] object by scanning the given packages. The meta data on the CorDapp will be the - * default values, which can be specified with the wither methods. + * default values, which can be changed with the wither methods. */ @JvmStatic fun fromPackages(packageNames: Collection): TestCordapp { return TestCordappImpl( - name = "test-cordapp", + name = "test-name", version = "1.0", vendor = "test-vendor", title = "test-title", diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/InternalMockNetwork.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/InternalMockNetwork.kt index e7cbd4717c..b9a5d535a9 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/InternalMockNetwork.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/InternalMockNetwork.kt @@ -251,12 +251,10 @@ open class InternalMockNetwork(defaultParameters: MockNetworkParameters = MockNe @VisibleForTesting internal open fun createNotaries(): List { - val version = VersionInfo(networkParameters.minimumPlatformVersion, "Mock release", "Mock revision", "Mock Vendor") return notarySpecs.map { (name, validating) -> createNode(InternalMockNodeParameters( legalName = name, - configOverrides = MockNodeConfigOverrides(notary = MockNetNotaryConfig(validating)), - version = version + configOverrides = MockNodeConfigOverrides(notary = MockNetNotaryConfig(validating)) )) } }