From be433c1fd092f34b3323eb59685ab945f0b59c53 Mon Sep 17 00:00:00 2001 From: Jose Coll <jose.coll@r3.com> Date: Tue, 24 Oct 2023 17:01:37 +0100 Subject: [PATCH 1/4] ENT-10100 Filter out UNVERIFIED txns + move TransactionStatus package. (#7543) --- .ci/api-current.txt | 192 +----------------- .../coretests/flows/FinalityFlowTests.kt | 2 +- .../net/corda/core/flows/RecoveryTypes.kt | 11 +- .../corda/core/flows/SendTransactionFlow.kt | 3 + .../net/corda/core/internal/FetchDataFlow.kt | 5 +- .../core/node/services/TransactionStorage.kt | 8 +- .../node/services/DbTransactionsResolver.kt | 2 +- .../persistence/DBTransactionStorage.kt | 8 +- .../node/internal/MockTransactionStorage.kt | 2 +- 9 files changed, 29 insertions(+), 204 deletions(-) diff --git a/.ci/api-current.txt b/.ci/api-current.txt index a7f5449ff7..79812632d4 100644 --- a/.ci/api-current.txt +++ b/.ci/api-current.txt @@ -1798,8 +1798,6 @@ public final class net.corda.core.crypto.Crypto extends java.lang.Object public static final boolean doVerify(net.corda.core.crypto.SecureHash, net.corda.core.crypto.TransactionSignature) public static final boolean doVerify(net.corda.core.crypto.SignatureScheme, java.security.PublicKey, byte[], byte[]) @NotNull - public static final byte[] encodePublicKey(java.security.PublicKey) - @NotNull public static final java.security.Provider findProvider(String) @NotNull public static final net.corda.core.crypto.SignatureScheme findSignatureScheme(int) @@ -2520,17 +2518,15 @@ public static final class net.corda.core.flows.ContractUpgradeFlow$Initiate exte protected net.corda.core.flows.AbstractStateReplacementFlow$UpgradeTx assembleTx() ## public class net.corda.core.flows.DataVendingFlow extends net.corda.core.flows.FlowLogic - public <init>(java.util.Set<? extends net.corda.core.flows.FlowSession>, Object, net.corda.core.flows.TransactionMetadata) - public <init>(java.util.Set, Object, net.corda.core.flows.TransactionMetadata, int, kotlin.jvm.internal.DefaultConstructorMarker) public <init>(net.corda.core.flows.FlowSession, Object) - public <init>(net.corda.core.flows.FlowSession, Object, net.corda.core.flows.TransactionMetadata) - public <init>(net.corda.core.flows.FlowSession, Object, net.corda.core.flows.TransactionMetadata, int, kotlin.jvm.internal.DefaultConstructorMarker) @Suspendable @Nullable public Void call() @NotNull public final java.util.Set<net.corda.core.flows.FlowSession> getOtherSessions() @NotNull + public final net.corda.core.flows.FlowSession getOtherSideSession() + @NotNull public final Object getPayload() @Suspendable @NotNull @@ -2541,61 +2537,10 @@ public class net.corda.core.flows.DataVendingFlow extends net.corda.core.flows.F @DoNotImplement public interface net.corda.core.flows.Destination ## -@CordaSerializable -public abstract class net.corda.core.flows.DistributionList extends java.lang.Object - public <init>(kotlin.jvm.internal.DefaultConstructorMarker) -## -@CordaSerializable -public static final class net.corda.core.flows.DistributionList$ReceiverDistributionList extends net.corda.core.flows.DistributionList - public <init>(byte[], net.corda.core.node.StatesToRecord) - @NotNull - public final byte[] component1() - @NotNull - public final net.corda.core.node.StatesToRecord component2() - @NotNull - public final net.corda.core.flows.DistributionList$ReceiverDistributionList copy(byte[], net.corda.core.node.StatesToRecord) - public boolean equals(Object) - @NotNull - public final byte[] getOpaqueData() - @NotNull - public final net.corda.core.node.StatesToRecord getReceiverStatesToRecord() - public int hashCode() - @NotNull - public String toString() -## -@CordaSerializable -public static final class net.corda.core.flows.DistributionList$SenderDistributionList extends net.corda.core.flows.DistributionList - public <init>(net.corda.core.node.StatesToRecord, java.util.Map<net.corda.core.identity.CordaX500Name, ? extends net.corda.core.node.StatesToRecord>) - @NotNull - public final net.corda.core.node.StatesToRecord component1() - @NotNull - public final java.util.Map<net.corda.core.identity.CordaX500Name, net.corda.core.node.StatesToRecord> component2() - @NotNull - public final net.corda.core.flows.DistributionList$SenderDistributionList copy(net.corda.core.node.StatesToRecord, java.util.Map<net.corda.core.identity.CordaX500Name, ? extends net.corda.core.node.StatesToRecord>) - public boolean equals(Object) - @NotNull - public final java.util.Map<net.corda.core.identity.CordaX500Name, net.corda.core.node.StatesToRecord> getPeersToStatesToRecord() - @NotNull - public final net.corda.core.node.StatesToRecord getSenderStatesToRecord() - public int hashCode() - @NotNull - public String toString() -@CordaSerializable -public abstract class net.corda.core.flows.DistributionRecord extends java.lang.Object implements net.corda.core.contracts.NamedByHash - public <init>() - @NotNull - public abstract net.corda.core.crypto.SecureHash getPeerPartyId() - @NotNull - public abstract java.time.Instant getTimestamp() - public abstract int getTimestampDiscriminator() - @NotNull - public abstract net.corda.core.crypto.SecureHash getTxId() -## @InitiatingFlow public final class net.corda.core.flows.FinalityFlow extends net.corda.core.flows.FlowLogic public <init>(net.corda.core.transactions.SignedTransaction) public <init>(net.corda.core.transactions.SignedTransaction, java.util.Collection<? extends net.corda.core.flows.FlowSession>) - public <init>(net.corda.core.transactions.SignedTransaction, java.util.Collection<? extends net.corda.core.flows.FlowSession>, java.util.Collection<? extends net.corda.core.flows.FlowSession>) public <init>(net.corda.core.transactions.SignedTransaction, java.util.Collection<? extends net.corda.core.flows.FlowSession>, java.util.Collection<net.corda.core.identity.Party>, net.corda.core.utilities.ProgressTracker) public <init>(net.corda.core.transactions.SignedTransaction, java.util.Collection<? extends net.corda.core.flows.FlowSession>, net.corda.core.node.StatesToRecord) public <init>(net.corda.core.transactions.SignedTransaction, java.util.Collection<? extends net.corda.core.flows.FlowSession>, net.corda.core.node.StatesToRecord, net.corda.core.utilities.ProgressTracker) @@ -2627,32 +2572,12 @@ public static final class net.corda.core.flows.FinalityFlow$Companion$BROADCASTI public static final net.corda.core.flows.FinalityFlow$Companion$BROADCASTING INSTANCE ## @CordaSerializable -public static final class net.corda.core.flows.FinalityFlow$Companion$BROADCASTING_NOTARY_ERROR extends net.corda.core.utilities.ProgressTracker$Step - public static final net.corda.core.flows.FinalityFlow$Companion$BROADCASTING_NOTARY_ERROR INSTANCE -## -@CordaSerializable -public static final class net.corda.core.flows.FinalityFlow$Companion$BROADCASTING_POST_NOTARISATION extends net.corda.core.utilities.ProgressTracker$Step - public static final net.corda.core.flows.FinalityFlow$Companion$BROADCASTING_POST_NOTARISATION INSTANCE -## -@CordaSerializable -public static final class net.corda.core.flows.FinalityFlow$Companion$BROADCASTING_PRE_NOTARISATION extends net.corda.core.utilities.ProgressTracker$Step - public static final net.corda.core.flows.FinalityFlow$Companion$BROADCASTING_PRE_NOTARISATION INSTANCE -## -@CordaSerializable -public static final class net.corda.core.flows.FinalityFlow$Companion$FINALISING_TRANSACTION extends net.corda.core.utilities.ProgressTracker$Step - public static final net.corda.core.flows.FinalityFlow$Companion$FINALISING_TRANSACTION INSTANCE -## -@CordaSerializable public static final class net.corda.core.flows.FinalityFlow$Companion$NOTARISING extends net.corda.core.utilities.ProgressTracker$Step @NotNull public net.corda.core.utilities.ProgressTracker childProgressTracker() public static final net.corda.core.flows.FinalityFlow$Companion$NOTARISING INSTANCE ## @CordaSerializable -public static final class net.corda.core.flows.FinalityFlow$Companion$RECORD_UNNOTARISED extends net.corda.core.utilities.ProgressTracker$Step - public static final net.corda.core.flows.FinalityFlow$Companion$RECORD_UNNOTARISED INSTANCE -## -@CordaSerializable public class net.corda.core.flows.FlowException extends net.corda.core.CordaException implements net.corda.core.flows.IdentifiableException public <init>() public <init>(String) @@ -2954,37 +2879,6 @@ public static final class net.corda.core.flows.FlowStackSnapshot$Frame extends j public String toString() ## @CordaSerializable -public final class net.corda.core.flows.FlowTransactionInfo extends java.lang.Object - public <init>(net.corda.core.flows.StateMachineRunId, String, net.corda.core.flows.TransactionStatus, java.time.Instant, net.corda.core.flows.TransactionMetadata) - @NotNull - public final net.corda.core.flows.StateMachineRunId component1() - @NotNull - public final String component2() - @NotNull - public final net.corda.core.flows.TransactionStatus component3() - @NotNull - public final java.time.Instant component4() - @Nullable - public final net.corda.core.flows.TransactionMetadata component5() - @NotNull - public final net.corda.core.flows.FlowTransactionInfo copy(net.corda.core.flows.StateMachineRunId, String, net.corda.core.flows.TransactionStatus, java.time.Instant, net.corda.core.flows.TransactionMetadata) - public boolean equals(Object) - @Nullable - public final net.corda.core.flows.TransactionMetadata getMetadata() - @NotNull - public final net.corda.core.flows.StateMachineRunId getStateMachineRunId() - @NotNull - public final net.corda.core.flows.TransactionStatus getStatus() - @NotNull - public final java.time.Instant getTimestamp() - @NotNull - public final String getTxId() - public int hashCode() - public final boolean isInitiator(net.corda.core.identity.CordaX500Name) - @NotNull - public String toString() -## -@CordaSerializable public class net.corda.core.flows.HospitalizeFlowException extends net.corda.core.CordaRuntimeException public <init>() public <init>(String) @@ -3246,10 +3140,6 @@ 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.NotarySigCheck extends java.lang.Object - public final boolean needsNotarySignature(net.corda.core.transactions.SignedTransaction) - public static final net.corda.core.flows.NotarySigCheck INSTANCE -## public final class net.corda.core.flows.ReceiveFinalityFlow extends net.corda.core.flows.FlowLogic public <init>(net.corda.core.flows.FlowSession) public <init>(net.corda.core.flows.FlowSession, net.corda.core.crypto.SecureHash) @@ -3277,41 +3167,6 @@ public class net.corda.core.flows.ReceiveTransactionFlow extends net.corda.core. protected void checkBeforeRecording(net.corda.core.transactions.SignedTransaction) ## @CordaSerializable -public final class net.corda.core.flows.RecoveryTimeWindow extends java.lang.Object - public <init>(java.time.Instant, java.time.Instant) - public <init>(java.time.Instant, java.time.Instant, int, kotlin.jvm.internal.DefaultConstructorMarker) - @NotNull - public static final net.corda.core.flows.RecoveryTimeWindow between(java.time.Instant, java.time.Instant) - @NotNull - public final java.time.Instant component1() - @NotNull - public final java.time.Instant component2() - @NotNull - public final net.corda.core.flows.RecoveryTimeWindow copy(java.time.Instant, java.time.Instant) - public boolean equals(Object) - @NotNull - public static final net.corda.core.flows.RecoveryTimeWindow fromOnly(java.time.Instant) - @NotNull - public final java.time.Instant getFromTime() - @NotNull - public final java.time.Instant getUntilTime() - public int hashCode() - @NotNull - public String toString() - @NotNull - public static final net.corda.core.flows.RecoveryTimeWindow untilOnly(java.time.Instant) - public static final net.corda.core.flows.RecoveryTimeWindow$Companion Companion -## -public static final class net.corda.core.flows.RecoveryTimeWindow$Companion extends java.lang.Object - public <init>(kotlin.jvm.internal.DefaultConstructorMarker) - @NotNull - public final net.corda.core.flows.RecoveryTimeWindow between(java.time.Instant, java.time.Instant) - @NotNull - public final net.corda.core.flows.RecoveryTimeWindow fromOnly(java.time.Instant) - @NotNull - public final net.corda.core.flows.RecoveryTimeWindow untilOnly(java.time.Instant) -## -@CordaSerializable public final class net.corda.core.flows.ResultSerializationException extends net.corda.core.CordaRuntimeException public <init>(net.corda.core.serialization.internal.MissingSerializerException) ## @@ -3322,12 +3177,6 @@ public class net.corda.core.flows.SendStateAndRefFlow extends net.corda.core.flo ## public class net.corda.core.flows.SendTransactionFlow extends net.corda.core.flows.DataVendingFlow public <init>(net.corda.core.flows.FlowSession, net.corda.core.transactions.SignedTransaction) - public static final net.corda.core.flows.SendTransactionFlow$Companion Companion -## -public static final class net.corda.core.flows.SendTransactionFlow$Companion extends java.lang.Object - public <init>(kotlin.jvm.internal.DefaultConstructorMarker) - @NotNull - public final net.corda.core.identity.CordaX500Name getDUMMY_PARTICIPANT_NAME() ## public abstract class net.corda.core.flows.SignTransactionFlow extends net.corda.core.flows.FlowLogic public <init>(net.corda.core.flows.FlowSession) @@ -3435,29 +3284,6 @@ public class net.corda.core.flows.StateReplacementException extends net.corda.co public <init>(String, Throwable, int, kotlin.jvm.internal.DefaultConstructorMarker) ## @CordaSerializable -public final class net.corda.core.flows.TransactionMetadata extends java.lang.Object - public <init>(net.corda.core.identity.CordaX500Name, net.corda.core.flows.DistributionList) - @NotNull - public final net.corda.core.identity.CordaX500Name component1() - @NotNull - public final net.corda.core.flows.DistributionList component2() - @NotNull - public final net.corda.core.flows.TransactionMetadata copy(net.corda.core.identity.CordaX500Name, net.corda.core.flows.DistributionList) - public boolean equals(Object) - @NotNull - public final net.corda.core.flows.DistributionList getDistributionList() - @NotNull - public final net.corda.core.identity.CordaX500Name getInitiator() - public int hashCode() - @NotNull - public String toString() -## -@CordaSerializable -public final class net.corda.core.flows.TransactionStatus extends java.lang.Enum - public static net.corda.core.flows.TransactionStatus valueOf(String) - public static net.corda.core.flows.TransactionStatus[] values() -## -@CordaSerializable public final class net.corda.core.flows.UnexpectedFlowEndException extends net.corda.core.CordaRuntimeException implements net.corda.core.flows.IdentifiableException public <init>(String) public <init>(String, Throwable) @@ -4317,7 +4143,6 @@ public interface net.corda.core.node.ServicesForResolution @NotNull public net.corda.core.transactions.LedgerTransaction specialise(net.corda.core.transactions.LedgerTransaction) ## -@CordaSerializable 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() @@ -4651,8 +4476,6 @@ public static final class net.corda.core.node.services.Vault$ConstraintInfo$Type @CordaSerializable public static final class net.corda.core.node.services.Vault$Page extends java.lang.Object public <init>(java.util.List<? extends net.corda.core.contracts.StateAndRef<? extends T>>, java.util.List<net.corda.core.node.services.Vault$StateMetadata>, long, net.corda.core.node.services.Vault$StateStatus, java.util.List<?>) - public <init>(java.util.List<? extends net.corda.core.contracts.StateAndRef<? extends T>>, java.util.List<net.corda.core.node.services.Vault$StateMetadata>, long, net.corda.core.node.services.Vault$StateStatus, java.util.List<?>, net.corda.core.contracts.StateRef) - public <init>(java.util.List, java.util.List, long, net.corda.core.node.services.Vault$StateStatus, java.util.List, net.corda.core.contracts.StateRef, int, kotlin.jvm.internal.DefaultConstructorMarker) @NotNull public final java.util.List<net.corda.core.contracts.StateAndRef<T>> component1() @NotNull @@ -4662,17 +4485,11 @@ public static final class net.corda.core.node.services.Vault$Page extends java.l public final net.corda.core.node.services.Vault$StateStatus component4() @NotNull public final java.util.List<Object> component5() - @Nullable - public final net.corda.core.contracts.StateRef component6() @NotNull public final net.corda.core.node.services.Vault$Page<T> copy(java.util.List<? extends net.corda.core.contracts.StateAndRef<? extends T>>, java.util.List<net.corda.core.node.services.Vault$StateMetadata>, long, net.corda.core.node.services.Vault$StateStatus, java.util.List<?>) - @NotNull - public final net.corda.core.node.services.Vault$Page<T> copy(java.util.List<? extends net.corda.core.contracts.StateAndRef<? extends T>>, java.util.List<net.corda.core.node.services.Vault$StateMetadata>, long, net.corda.core.node.services.Vault$StateStatus, java.util.List<?>, net.corda.core.contracts.StateRef) public boolean equals(Object) @NotNull public final java.util.List<Object> getOtherResults() - @Nullable - public final net.corda.core.contracts.StateRef getPreviousPageAnchor() @NotNull public final net.corda.core.node.services.Vault$StateStatus getStateTypes() @NotNull @@ -8233,6 +8050,8 @@ public static final class net.corda.testing.core.TestIdentity$Companion extends 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 + public static final java.security.cert.X509CRL createCRL(net.corda.nodeapi.internal.crypto.CertificateAndKeyPair, java.util.List<? extends java.security.cert.X509Certificate>, java.net.URI, java.time.Instant, java.time.Instant, boolean, java.time.Instant, int, String) public static final T executeTest(java.time.Duration, kotlin.jvm.functions.Function0<kotlin.Unit>, java.time.Duration, kotlin.jvm.functions.Function0<? extends T>) @NotNull public static final net.corda.core.utilities.NetworkHostAndPort freeLocalHostAndPort() @@ -8907,7 +8726,6 @@ public final class net.corda.testing.flows.FlowTestsUtilsKt extends java.lang.Ob public static final java.util.Map<net.corda.core.flows.FlowSession, net.corda.core.utilities.UntrustworthyData<Object>> receiveAll(net.corda.core.flows.FlowLogic<?>, kotlin.Pair<? extends net.corda.core.flows.FlowSession, ? extends Class<?>>, kotlin.Pair<? extends net.corda.core.flows.FlowSession, ? extends Class<?>>...) @NotNull public static final rx.Observable<T> registerCoreFlowFactory(net.corda.testing.node.internal.TestStartedNode, Class<? extends net.corda.core.flows.FlowLogic<?>>, Class<T>, kotlin.jvm.functions.Function1<? super net.corda.core.flows.FlowSession, ? extends T>, boolean) - public static final void waitForAllFlowsToComplete(net.corda.testing.driver.NodeHandle, int, long) ## @DoNotImplement public abstract class net.corda.testing.node.ClusterSpec extends java.lang.Object @@ -9329,9 +9147,7 @@ public class net.corda.testing.node.MockServices extends java.lang.Object implem @NotNull public static final kotlin.Pair<net.corda.nodeapi.internal.persistence.CordaPersistence, net.corda.testing.node.MockServices> makeTestDatabaseAndPersistentServices(java.util.List<String>, net.corda.testing.core.TestIdentity, net.corda.core.node.NetworkParameters, java.util.Set<java.security.KeyPair>, java.util.Set<net.corda.core.identity.PartyAndCertificate>, net.corda.testing.internal.TestingNamedCacheFactory) public void recordTransactions(Iterable<net.corda.core.transactions.SignedTransaction>) - public final void recordTransactions(Iterable<net.corda.core.transactions.SignedTransaction>, boolean) public void recordTransactions(net.corda.core.node.StatesToRecord, Iterable<net.corda.core.transactions.SignedTransaction>) - public final void recordTransactions(net.corda.core.transactions.SignedTransaction, boolean) public void recordTransactions(net.corda.core.transactions.SignedTransaction, net.corda.core.transactions.SignedTransaction...) public void recordTransactions(boolean, Iterable<net.corda.core.transactions.SignedTransaction>) public void recordTransactions(boolean, net.corda.core.transactions.SignedTransaction, net.corda.core.transactions.SignedTransaction...) diff --git a/core-tests/src/test/kotlin/net/corda/coretests/flows/FinalityFlowTests.kt b/core-tests/src/test/kotlin/net/corda/coretests/flows/FinalityFlowTests.kt index 562cc3a4b4..4eb85ec26b 100644 --- a/core-tests/src/test/kotlin/net/corda/coretests/flows/FinalityFlowTests.kt +++ b/core-tests/src/test/kotlin/net/corda/coretests/flows/FinalityFlowTests.kt @@ -25,7 +25,6 @@ import net.corda.core.flows.ReceiverDistributionRecord import net.corda.core.flows.SendTransactionFlow import net.corda.core.flows.SenderDistributionRecord import net.corda.core.flows.StartableByRPC -import net.corda.core.flows.TransactionStatus import net.corda.core.flows.UnexpectedFlowEndException import net.corda.core.identity.CordaX500Name import net.corda.core.identity.Party @@ -34,6 +33,7 @@ import net.corda.core.internal.PLATFORM_VERSION import net.corda.core.internal.PlatformVersionSwitches import net.corda.core.internal.ServiceHubCoreInternal import net.corda.core.node.StatesToRecord +import net.corda.core.node.services.TransactionStatus import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.OpaqueBytes diff --git a/core/src/main/kotlin/net/corda/core/flows/RecoveryTypes.kt b/core/src/main/kotlin/net/corda/core/flows/RecoveryTypes.kt index ae5d3ee4e6..b04de15187 100644 --- a/core/src/main/kotlin/net/corda/core/flows/RecoveryTypes.kt +++ b/core/src/main/kotlin/net/corda/core/flows/RecoveryTypes.kt @@ -1,9 +1,11 @@ package net.corda.core.flows +import net.corda.core.DoNotImplement import net.corda.core.contracts.NamedByHash import net.corda.core.crypto.SecureHash import net.corda.core.identity.CordaX500Name import net.corda.core.node.StatesToRecord +import net.corda.core.node.services.TransactionStatus import net.corda.core.serialization.CordaSerializable import net.corda.core.utilities.OpaqueBytes import java.time.Instant @@ -32,6 +34,7 @@ data class TransactionMetadata( ) @CordaSerializable +@DoNotImplement sealed class DistributionList { @CordaSerializable @@ -47,13 +50,6 @@ sealed class DistributionList { ) : DistributionList() } -@CordaSerializable -enum class TransactionStatus { - UNVERIFIED, - VERIFIED, - IN_FLIGHT; -} - @CordaSerializable class DistributionRecords( val senderRecords: List<SenderDistributionRecord> = emptyList(), @@ -63,6 +59,7 @@ class DistributionRecords( } @CordaSerializable +@DoNotImplement abstract class DistributionRecord : NamedByHash { abstract val txId: SecureHash abstract val peerPartyId: SecureHash diff --git a/core/src/main/kotlin/net/corda/core/flows/SendTransactionFlow.kt b/core/src/main/kotlin/net/corda/core/flows/SendTransactionFlow.kt index 9f57de9580..92811e5965 100644 --- a/core/src/main/kotlin/net/corda/core/flows/SendTransactionFlow.kt +++ b/core/src/main/kotlin/net/corda/core/flows/SendTransactionFlow.kt @@ -122,6 +122,9 @@ open class DataVendingFlow(val otherSessions: Set<FlowSession>, val payload: Any constructor(otherSideSession: FlowSession, payload: Any, txnMetadata: TransactionMetadata? = null) : this(setOf(otherSideSession), payload, txnMetadata) constructor(otherSideSession: FlowSession, payload: Any) : this(otherSideSession, payload, null) + @Deprecated("Use otherSessions: Set<FlowSession>", replaceWith = ReplaceWith("otherSessions.single()")) + val otherSideSession: FlowSession get() = otherSessions.single() + @Suspendable protected open fun sendPayloadAndReceiveDataRequest(otherSideSession: FlowSession, payload: Any) = otherSideSession.sendAndReceive<FetchDataFlow.Request>(payload) diff --git a/core/src/main/kotlin/net/corda/core/internal/FetchDataFlow.kt b/core/src/main/kotlin/net/corda/core/internal/FetchDataFlow.kt index 1479ab4896..44367159f6 100644 --- a/core/src/main/kotlin/net/corda/core/internal/FetchDataFlow.kt +++ b/core/src/main/kotlin/net/corda/core/internal/FetchDataFlow.kt @@ -13,6 +13,7 @@ import net.corda.core.internal.FetchDataFlow.DownloadedVsRequestedDataMismatch import net.corda.core.internal.FetchDataFlow.HashNotFound import net.corda.core.node.NetworkParameters import net.corda.core.node.services.SignedTransactionWithStatus +import net.corda.core.node.services.TransactionStatus import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializationTransformEnumDefault import net.corda.core.serialization.CordaSerializationTransformEnumDefaults @@ -278,7 +279,9 @@ class FetchTransactionsFlow @JvmOverloads constructor(requests: Set<SecureHash>, class FetchRecoverableTransactionsFlow @JvmOverloads constructor(requests: Set<SecureHash>, otherSide: FlowSession, dataType: DataType = DataType.TRANSACTION_RECOVERY) : FetchDataFlow<SignedTransactionWithStatus, SignedTransactionWithStatus>(requests, otherSide, dataType) { - override fun load(txid: SecureHash): SignedTransactionWithStatus? = serviceHub.validatedTransactions.getTransactionWithStatus(txid) + override fun load(txid: SecureHash): SignedTransactionWithStatus? = serviceHub.validatedTransactions.getTransactionWithStatus(txid)?.let { + if (it.status != TransactionStatus.UNVERIFIED) it else null + } } class FetchBatchTransactionsFlow(requests: Set<SecureHash>, otherSide: FlowSession) : diff --git a/core/src/main/kotlin/net/corda/core/node/services/TransactionStorage.kt b/core/src/main/kotlin/net/corda/core/node/services/TransactionStorage.kt index b4875040e0..a68716a6d3 100644 --- a/core/src/main/kotlin/net/corda/core/node/services/TransactionStorage.kt +++ b/core/src/main/kotlin/net/corda/core/node/services/TransactionStorage.kt @@ -4,7 +4,6 @@ import net.corda.core.DoNotImplement import net.corda.core.concurrent.CordaFuture import net.corda.core.contracts.NamedByHash import net.corda.core.crypto.SecureHash -import net.corda.core.flows.TransactionStatus import net.corda.core.messaging.DataFeed import net.corda.core.serialization.CordaSerializable import net.corda.core.transactions.SignedTransaction @@ -49,4 +48,11 @@ data class SignedTransactionWithStatus( ) : NamedByHash { override val id: SecureHash get() = stx.id +} + +@CordaSerializable +enum class TransactionStatus { + UNVERIFIED, + VERIFIED, + IN_FLIGHT; } \ No newline at end of file diff --git a/node/src/main/kotlin/net/corda/node/services/DbTransactionsResolver.kt b/node/src/main/kotlin/net/corda/node/services/DbTransactionsResolver.kt index e82549d8e3..668b95ff92 100644 --- a/node/src/main/kotlin/net/corda/node/services/DbTransactionsResolver.kt +++ b/node/src/main/kotlin/net/corda/node/services/DbTransactionsResolver.kt @@ -3,12 +3,12 @@ package net.corda.node.services import co.paralleluniverse.fibers.Suspendable import net.corda.core.crypto.SecureHash import net.corda.core.flows.FlowLogic -import net.corda.core.flows.TransactionStatus import net.corda.core.internal.FetchTransactionsFlow import net.corda.core.internal.ResolveTransactionsFlow import net.corda.core.internal.TransactionsResolver import net.corda.core.internal.dependencies import net.corda.core.node.StatesToRecord +import net.corda.core.node.services.TransactionStatus import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.debug import net.corda.core.utilities.seconds diff --git a/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionStorage.kt b/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionStorage.kt index 8577afe934..b66dedb22b 100644 --- a/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionStorage.kt +++ b/node/src/main/kotlin/net/corda/node/services/persistence/DBTransactionStorage.kt @@ -98,11 +98,11 @@ open class DBTransactionStorage(private val database: CordaPersistence, cacheFac return this == VERIFIED } - fun toTransactionStatus(): net.corda.core.flows.TransactionStatus { + fun toTransactionStatus(): net.corda.core.node.services.TransactionStatus { return when(this) { - UNVERIFIED -> net.corda.core.flows.TransactionStatus.UNVERIFIED - VERIFIED -> net.corda.core.flows.TransactionStatus.VERIFIED - IN_FLIGHT -> net.corda.core.flows.TransactionStatus.IN_FLIGHT + UNVERIFIED -> net.corda.core.node.services.TransactionStatus.UNVERIFIED + VERIFIED -> net.corda.core.node.services.TransactionStatus.VERIFIED + IN_FLIGHT -> net.corda.core.node.services.TransactionStatus.IN_FLIGHT } } diff --git a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/MockTransactionStorage.kt b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/MockTransactionStorage.kt index d09af76ca2..ee4a4a91f5 100644 --- a/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/MockTransactionStorage.kt +++ b/testing/node-driver/src/main/kotlin/net/corda/testing/node/internal/MockTransactionStorage.kt @@ -10,9 +10,9 @@ import net.corda.core.toFuture import net.corda.core.transactions.SignedTransaction import net.corda.node.services.api.WritableTransactionStorage import net.corda.core.flows.TransactionMetadata -import net.corda.core.flows.TransactionStatus import net.corda.core.identity.CordaX500Name import net.corda.core.node.services.SignedTransactionWithStatus +import net.corda.core.node.services.TransactionStatus import net.corda.testing.node.MockServices import rx.Observable import rx.subjects.PublishSubject From be515abd0892ea3ef08db1b38881d14e9fa62d37 Mon Sep 17 00:00:00 2001 From: Jose Coll <jose.coll@r3.com> Date: Tue, 24 Oct 2023 17:02:17 +0100 Subject: [PATCH 2/4] ENT-11004 Store Ledger Recovery records only if the transaction was locally stored in the first place. (#7544) --- .../main/kotlin/net/corda/core/flows/SendTransactionFlow.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/core/src/main/kotlin/net/corda/core/flows/SendTransactionFlow.kt b/core/src/main/kotlin/net/corda/core/flows/SendTransactionFlow.kt index 92811e5965..93a0f59852 100644 --- a/core/src/main/kotlin/net/corda/core/flows/SendTransactionFlow.kt +++ b/core/src/main/kotlin/net/corda/core/flows/SendTransactionFlow.kt @@ -90,7 +90,7 @@ open class SendTransactionFlow(val stx: SignedTransaction, val DUMMY_PARTICIPANT_NAME = CordaX500Name("Transaction Participant", "London", "GB") fun makeMetaData(stx: SignedTransaction, recordMetaDataEvenIfNotFullySigned: Boolean, senderStatesToRecord: StatesToRecord, participantSessions: Set<FlowSession>, observerSessions: Set<FlowSession>): TransactionMetadata? { - return if (recordMetaDataEvenIfNotFullySigned || isFullySigned(stx)) + return if (recordMetaDataEvenIfNotFullySigned || isFullySignedAndStoredLocally(stx)) TransactionMetadata(DUMMY_PARTICIPANT_NAME, SenderDistributionList(senderStatesToRecord, (participantSessions.map { it.counterparty.name to StatesToRecord.ONLY_RELEVANT }).toMap() + @@ -104,6 +104,9 @@ open class SendTransactionFlow(val stx: SignedTransaction, stx.resolveTransactionWithSignatures(serviceHub).getMissingSigners().isEmpty() else false } + + private fun isFullySignedAndStoredLocally(stx: SignedTransaction) = isFullySigned(stx) + && (currentTopLevel?.serviceHub?.validatedTransactions?.getTransaction(stx.id) != null) } } From e52f086d1179b56bd2c505e6cff04842ade9a420 Mon Sep 17 00:00:00 2001 From: Jose Coll <jose.coll@r3.com> Date: Thu, 26 Oct 2023 09:38:52 +0100 Subject: [PATCH 3/4] ENT-11036 Additional parameter to enable recovery of IN_FLIGHT transactions (post ledger peer recovery) (#7546) --- .../src/main/kotlin/net/corda/core/flows/LedgerRecoverFlow.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/src/main/kotlin/net/corda/core/flows/LedgerRecoverFlow.kt b/core/src/main/kotlin/net/corda/core/flows/LedgerRecoverFlow.kt index f416fe1455..5153f98e91 100644 --- a/core/src/main/kotlin/net/corda/core/flows/LedgerRecoverFlow.kt +++ b/core/src/main/kotlin/net/corda/core/flows/LedgerRecoverFlow.kt @@ -37,12 +37,14 @@ data class LedgerRecoveryParameters( val dryRun: Boolean = false, val useTimeWindowNarrowing: Boolean = true, val verboseLogging: Boolean = false, - val recoveryBatchSize: Int = 1000 + val recoveryBatchSize: Int = 1000, + val alsoFinalize: Boolean = false ) @CordaSerializable data class LedgerRecoveryResult( val totalRecoveredRecords: Long, val totalRecoveredTransactions: Long, + val totalRecoveredInFlightTransactions: Long, val totalErrors: Long ) From c626d3a43562f721c9a38ab796d21930def8ab93 Mon Sep 17 00:00:00 2001 From: Rick Parker <rick.parker@r3.com> Date: Fri, 27 Oct 2023 13:26:07 +0100 Subject: [PATCH 4/4] ENT-10100: fix batch support during recovery of in flight transactions (#7549) --- .../corda/core/flows/SendTransactionFlow.kt | 19 +++++++++--- .../net/corda/core/internal/FetchDataFlow.kt | 27 +++++++----------- .../internal/amqp/EvolvabilityTests.kt | 17 +++++++++++ ...olvabilityTests.maybeSerializedTransaction | Bin 0 -> 4019 bytes 4 files changed, 42 insertions(+), 21 deletions(-) create mode 100644 serialization/src/test/resources/net/corda/serialization/internal/amqp/EvolvabilityTests.maybeSerializedTransaction diff --git a/core/src/main/kotlin/net/corda/core/flows/SendTransactionFlow.kt b/core/src/main/kotlin/net/corda/core/flows/SendTransactionFlow.kt index 93a0f59852..173107dd5f 100644 --- a/core/src/main/kotlin/net/corda/core/flows/SendTransactionFlow.kt +++ b/core/src/main/kotlin/net/corda/core/flows/SendTransactionFlow.kt @@ -4,11 +4,18 @@ import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.NamedByHash import net.corda.core.contracts.StateAndRef import net.corda.core.crypto.SecureHash +import net.corda.core.flows.DistributionList.SenderDistributionList import net.corda.core.identity.CordaX500Name -import net.corda.core.internal.* +import net.corda.core.internal.FetchDataFlow +import net.corda.core.internal.NetworkParametersStorage +import net.corda.core.internal.PlatformVersionSwitches +import net.corda.core.internal.RetrieveAnyTransactionPayload +import net.corda.core.internal.ServiceHubCoreInternal +import net.corda.core.internal.readFully import net.corda.core.node.ServicesForResolution import net.corda.core.node.StatesToRecord import net.corda.core.serialization.CordaSerializable +import net.corda.core.serialization.DeprecatedConstructorForDeserialization import net.corda.core.serialization.SerializedBytes import net.corda.core.serialization.deserialize import net.corda.core.serialization.serialize @@ -16,7 +23,6 @@ import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.trace import net.corda.core.utilities.unwrap import kotlin.collections.toSet -import net.corda.core.flows.DistributionList.SenderDistributionList /** * In the words of Matt working code is more important then pretty code. This class that contains code that may @@ -27,7 +33,12 @@ import net.corda.core.flows.DistributionList.SenderDistributionList */ @CordaSerializable class MaybeSerializedSignedTransaction(override val id: SecureHash, val serialized: SerializedBytes<SignedTransaction>?, - val nonSerialised: SignedTransaction?) : NamedByHash { + val nonSerialised: SignedTransaction?, + val inFlight: Boolean) : NamedByHash { + + @DeprecatedConstructorForDeserialization(version = 1) + constructor(id: SecureHash, serialized: SerializedBytes<SignedTransaction>?, nonSerialised: SignedTransaction?) : this(id, serialized, nonSerialised, false) + init { check(serialized == null || nonSerialised == null) { "MaybeSerializedSignedTransaction: Serialized and non-serialized may not both be non-null." @@ -227,7 +238,7 @@ open class DataVendingFlow(val otherSessions: Set<FlowSession>, val payload: Any numSent++ tx } - FetchDataFlow.DataType.TRANSACTION_RECOVERY -> NotImplementedError("Enterprise only feature") + FetchDataFlow.DataType.TRANSACTION_RECOVERY -> throw NotImplementedError("Enterprise only feature") // Loop on all items returned using dataRequest.hashes.map: FetchDataFlow.DataType.BATCH_TRANSACTION -> dataRequest.hashes.map { txId -> if (!authorisedTransactions.isAuthorised(txId)) { diff --git a/core/src/main/kotlin/net/corda/core/internal/FetchDataFlow.kt b/core/src/main/kotlin/net/corda/core/internal/FetchDataFlow.kt index 44367159f6..07564bcbf4 100644 --- a/core/src/main/kotlin/net/corda/core/internal/FetchDataFlow.kt +++ b/core/src/main/kotlin/net/corda/core/internal/FetchDataFlow.kt @@ -12,7 +12,6 @@ import net.corda.core.flows.MaybeSerializedSignedTransaction import net.corda.core.internal.FetchDataFlow.DownloadedVsRequestedDataMismatch import net.corda.core.internal.FetchDataFlow.HashNotFound import net.corda.core.node.NetworkParameters -import net.corda.core.node.services.SignedTransactionWithStatus import net.corda.core.node.services.TransactionStatus import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializationTransformEnumDefault @@ -24,10 +23,11 @@ import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.NonEmptySet import net.corda.core.utilities.UntrustworthyData import net.corda.core.utilities.debug -import net.corda.core.utilities.unwrap import net.corda.core.utilities.trace +import net.corda.core.utilities.unwrap import java.nio.file.FileAlreadyExistsException -import java.util.* +import java.util.ArrayList +import java.util.LinkedHashSet /** * An abstract flow for fetching typed data from a remote peer. @@ -275,24 +275,17 @@ class FetchTransactionsFlow @JvmOverloads constructor(requests: Set<SecureHash>, override fun load(txid: SecureHash): SignedTransaction? = serviceHub.validatedTransactions.getTransaction(txid) } -// Used by Enterprise Ledger Recovery -class FetchRecoverableTransactionsFlow @JvmOverloads constructor(requests: Set<SecureHash>, otherSide: FlowSession, dataType: DataType = DataType.TRANSACTION_RECOVERY) : - FetchDataFlow<SignedTransactionWithStatus, SignedTransactionWithStatus>(requests, otherSide, dataType) { - - override fun load(txid: SecureHash): SignedTransactionWithStatus? = serviceHub.validatedTransactions.getTransactionWithStatus(txid)?.let { - if (it.status != TransactionStatus.UNVERIFIED) it else null - } -} - -class FetchBatchTransactionsFlow(requests: Set<SecureHash>, otherSide: FlowSession) : - FetchDataFlow<MaybeSerializedSignedTransaction, MaybeSerializedSignedTransaction>(requests, otherSide, DataType.BATCH_TRANSACTION) { +class FetchBatchTransactionsFlow(requests: Set<SecureHash>, otherSide: FlowSession, private val recoveryMode: Boolean = false) : + FetchDataFlow<MaybeSerializedSignedTransaction, MaybeSerializedSignedTransaction>(requests, otherSide, + if (recoveryMode) DataType.TRANSACTION_RECOVERY else DataType.BATCH_TRANSACTION) { override fun load(txid: SecureHash): MaybeSerializedSignedTransaction? { - val tran = serviceHub.validatedTransactions.getTransaction(txid) - return if (tran == null) { + val tranAndStatus = serviceHub.validatedTransactions.getTransactionWithStatus(txid) + @Suppress("ComplexCondition") + return if (tranAndStatus == null || tranAndStatus.status == TransactionStatus.UNVERIFIED || (!recoveryMode && tranAndStatus.status == TransactionStatus.IN_FLIGHT)) { null } else { - MaybeSerializedSignedTransaction(txid, null, tran) + MaybeSerializedSignedTransaction(txid, null, tranAndStatus.stx, tranAndStatus.status == TransactionStatus.IN_FLIGHT) } } } diff --git a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/EvolvabilityTests.kt b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/EvolvabilityTests.kt index 9514a65626..0c2ecdb8c9 100644 --- a/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/EvolvabilityTests.kt +++ b/serialization/src/test/kotlin/net/corda/serialization/internal/amqp/EvolvabilityTests.kt @@ -4,6 +4,7 @@ import net.corda.core.crypto.Crypto import net.corda.core.crypto.Crypto.generateKeyPair import net.corda.core.crypto.SignedData import net.corda.core.crypto.sign +import net.corda.core.flows.MaybeSerializedSignedTransaction import net.corda.core.flows.NotarisationRequest import net.corda.core.identity.CordaX500Name import net.corda.core.identity.Party @@ -21,6 +22,7 @@ import net.corda.serialization.internal.amqp.testutils.serialize import net.corda.serialization.internal.amqp.testutils.serializeAndReturnSchema import net.corda.serialization.internal.amqp.testutils.testDefaultFactory import net.corda.serialization.internal.amqp.testutils.testName +import org.assertj.core.api.Assertions.assertThat import org.junit.Ignore import org.junit.Test import org.junit.jupiter.api.Assertions.assertNotSame @@ -921,4 +923,19 @@ class EvolvabilityTests { assertNotSame(deserialized2.statesToConsume[0].txhash, deserialized2.statesToConsume[1].txhash) assertNotSame(deserialized2.statesToConsume[2].txhash, deserialized2.statesToConsume[3].txhash) } + + @Test(timeout = 300_000) + fun maybeSerializedTransaction() { + val sf = testDefaultFactory() + val resource = "EvolvabilityTests.maybeSerializedTransaction" + + //val A = MaybeSerializedSignedTransaction(SecureHash.randomSHA256(), null, null) + //File(URI("$localPath/$resource")).writeBytes(SerializationOutput(sf).serialize(A).bytes) + + val url = EvolvabilityTests::class.java.getResource(resource) + val sc2 = url.readBytes() + val deserializedA = DeserializationInput(sf).deserialize(SerializedBytes<MaybeSerializedSignedTransaction>(sc2)) + + assertThat(deserializedA).isInstanceOf(MaybeSerializedSignedTransaction::class.java) + } } diff --git a/serialization/src/test/resources/net/corda/serialization/internal/amqp/EvolvabilityTests.maybeSerializedTransaction b/serialization/src/test/resources/net/corda/serialization/internal/amqp/EvolvabilityTests.maybeSerializedTransaction new file mode 100644 index 0000000000000000000000000000000000000000..8da04d34d38ad943ec2ae4a9a91db77f63b76a6c GIT binary patch literal 4019 zcmc&%&2Jk;6!$vbm?F`tq9{@&P!$42F*tD&J5C{yKjOrW<L{3&Mk<<JkL`8VyY|jF z-t~zC7tSETfdfOYs0UPu3y0~U>IDh@10*EQNFXHO0=sU!wbyp)v{+m$Yv=8IzxR8; z_uecoD`mjgY_<;{a{8~$#{6irUHL-)GiSTIC_(Jz4U1a|DV`~KVwpWY+|1R>UX&GF zt<3f|O$^(ql~PLfX12IeIGaNJCdh~L5yS3v=F1zuCcb^+&r1*Q{q^Yn*X+XLcfkAc zPuH&B`C0htQ|*@zgwF#36NcS@@xmFN%m3(qu9|18e#YF@AF;%1A~bM9cSV#t$ejQh z2XjynfGBifIVV&lSk5azLV(ADECuLIhAdfL<z)#g`Z;nZK?9aUS`?s~8FP-lX`hCV zfPu}~qp#1XgTCz~cA-peSR*Q06U*)#<l71~qD2CMV8{&Vpu0};k|axKnIKpu?^s;u zi2F$)_eh?)ztEsR*-2hRCN1QBi?jX_FgVg-_4x~F7^3$q#^*=g84k_TkJ#x5{|`!o z57bWbq<tD!VxiNrr~vNZpr}hQ5HYD`>EG<r%MqYE40*Q>PJvqlQq>)n8%?0Q6QPxi zHWowy3lO;tu5z%|h7u2V%y?GyWTckj4~Mh3)$*u~?x`FTg?$4e<>t(n9P||@VL5|* zGS3MTP&BJRbc1=hQb7=tIYGh^!mJJ}=w&ByAiW319<%ft_PO$#9YLE7DbmaVX{%c} zY5P5L(RW*wI>R+II_<OG6u4Md1n3?6$lw@~bN)$J9SOK*^cBE*kD}=`Y*uij?A_{K zz7gE;Z0)<a=*mhgii%p$DEkj~^CbsO^omwRgjuHB47t@)pdm5$p@6Ved;H@mGJx5{ zyJMLrf-V=Vh6Ierv8A1#z4ycV+#LvRbpF5)W9j#!Q+hhG|Gzq|Nx^8zn`*?Aq*(Wf zv6vDqM26KjPu2P7s!W79M7^43*{xbxUsKi2>TT?)wo;{L-m{ij^&VTM*pm)ewv_W6 zQOvGscUSyMC)4o-xnjF^eCW^Aa;0cb-oH7_JRS5ceH(I`A@1u8S?Gxy87ol0nmgU* zM1hY(ZAe5@Ou~?pT-Ap&)>nQ4Dkq{YNeIc!@wB9^hQr&+K@D%H-}MQIK^b5$$(z}3 zeM4&pe8NsnlZNLe9+IoW<mj}JYrRK;acg+Io{e>6l4})_wuw4nHNCgqc7;GRn+z2b z)f0<|C}zh53eaWyn8z24&ld}l+~8aXLOt75HkyZP(ynSKVsI6g+3{Wjbb%RvGBID? zvtEvFcH`}%<i6@s65g`dlC1IWv6Ct}qKg5XR%$b)z0?NsOVyRS1XHRHgtxpay%nBh zOneR+)MvRO%b2WBDaEBT5QcuOLONle$;~-gwB*CXTKL$rnJ#sT$*eDOq*g*zOM&iB zBy2?b=Y)!N_pqPO#x;x%TI;77msUsnMktyeTz;=P$(5!Ea79)cMW`VCDmwP^;-IfO z$z{aXU;`%G4Gt=?-LZx&{hgiRx|`iN4SVw$Asb3Xf)!Uh<?(d$^+LL*u*E@zJ>`<f z(m&Xl-t=cj08SKRE>M)yEe)oE8|kDg?Jx8cb1?!QOxCaY>9v%L2G_j4*(EdS!#F@M KlFX$CjO}0SepMy_ literal 0 HcmV?d00001