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 (java.util.Set, Object, net.corda.core.flows.TransactionMetadata) - public (java.util.Set, Object, net.corda.core.flows.TransactionMetadata, int, kotlin.jvm.internal.DefaultConstructorMarker) public (net.corda.core.flows.FlowSession, Object) - public (net.corda.core.flows.FlowSession, Object, net.corda.core.flows.TransactionMetadata) - public (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 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 (kotlin.jvm.internal.DefaultConstructorMarker) -## -@CordaSerializable -public static final class net.corda.core.flows.DistributionList$ReceiverDistributionList extends net.corda.core.flows.DistributionList - public (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 (net.corda.core.node.StatesToRecord, java.util.Map) - @NotNull - public final net.corda.core.node.StatesToRecord component1() - @NotNull - public final java.util.Map component2() - @NotNull - public final net.corda.core.flows.DistributionList$SenderDistributionList copy(net.corda.core.node.StatesToRecord, java.util.Map) - public boolean equals(Object) - @NotNull - public final java.util.Map 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 () - @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 (net.corda.core.transactions.SignedTransaction) public (net.corda.core.transactions.SignedTransaction, java.util.Collection) - public (net.corda.core.transactions.SignedTransaction, java.util.Collection, java.util.Collection) public (net.corda.core.transactions.SignedTransaction, java.util.Collection, java.util.Collection, net.corda.core.utilities.ProgressTracker) public (net.corda.core.transactions.SignedTransaction, java.util.Collection, net.corda.core.node.StatesToRecord) public (net.corda.core.transactions.SignedTransaction, java.util.Collection, 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 () public (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 (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 () public (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 (net.corda.core.flows.FlowSession) public (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 (java.time.Instant, java.time.Instant) - public (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 (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 (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 (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 (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 (net.corda.core.flows.FlowSession) @@ -3435,29 +3284,6 @@ public class net.corda.core.flows.StateReplacementException extends net.corda.co public (String, Throwable, int, kotlin.jvm.internal.DefaultConstructorMarker) ## @CordaSerializable -public final class net.corda.core.flows.TransactionMetadata extends java.lang.Object - public (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 (String) public (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 (java.util.List>, java.util.List, long, net.corda.core.node.services.Vault$StateStatus, java.util.List) - public (java.util.List>, java.util.List, long, net.corda.core.node.services.Vault$StateStatus, java.util.List, net.corda.core.contracts.StateRef) - public (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> 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 component5() - @Nullable - public final net.corda.core.contracts.StateRef component6() @NotNull public final net.corda.core.node.services.Vault$Page copy(java.util.List>, java.util.List, long, net.corda.core.node.services.Vault$StateStatus, java.util.List) - @NotNull - public final net.corda.core.node.services.Vault$Page copy(java.util.List>, java.util.List, 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 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, 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, java.time.Duration, kotlin.jvm.functions.Function0) @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> receiveAll(net.corda.core.flows.FlowLogic, kotlin.Pair>, kotlin.Pair>...) @NotNull public static final rx.Observable registerCoreFlowFactory(net.corda.testing.node.internal.TestStartedNode, Class>, Class, kotlin.jvm.functions.Function1, 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 makeTestDatabaseAndPersistentServices(java.util.List, net.corda.testing.core.TestIdentity, net.corda.core.node.NetworkParameters, java.util.Set, java.util.Set, net.corda.testing.internal.TestingNamedCacheFactory) public void recordTransactions(Iterable) - public final void recordTransactions(Iterable, boolean) public void recordTransactions(net.corda.core.node.StatesToRecord, Iterable) - 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) 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/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 ) 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 = 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..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?, - val nonSerialised: SignedTransaction?) : NamedByHash { + val nonSerialised: SignedTransaction?, + val inFlight: Boolean) : NamedByHash { + + @DeprecatedConstructorForDeserialization(version = 1) + constructor(id: SecureHash, serialized: SerializedBytes?, nonSerialised: SignedTransaction?) : this(id, serialized, nonSerialised, false) + init { check(serialized == null || nonSerialised == null) { "MaybeSerializedSignedTransaction: Serialized and non-serialized may not both be non-null." @@ -90,7 +101,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, observerSessions: Set): 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 +115,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) } } @@ -122,6 +136,9 @@ open class DataVendingFlow(val otherSessions: Set, 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", replaceWith = ReplaceWith("otherSessions.single()")) + val otherSideSession: FlowSession get() = otherSessions.single() + @Suspendable protected open fun sendPayloadAndReceiveDataRequest(otherSideSession: FlowSession, payload: Any) = otherSideSession.sendAndReceive(payload) @@ -221,7 +238,7 @@ open class DataVendingFlow(val otherSessions: Set, 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 1479ab4896..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,7 @@ 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 import net.corda.core.serialization.CordaSerializationTransformEnumDefaults @@ -23,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. @@ -274,22 +275,17 @@ class FetchTransactionsFlow @JvmOverloads constructor(requests: Set, override fun load(txid: SecureHash): SignedTransaction? = serviceHub.validatedTransactions.getTransaction(txid) } -// Used by Enterprise Ledger Recovery -class FetchRecoverableTransactionsFlow @JvmOverloads constructor(requests: Set, otherSide: FlowSession, dataType: DataType = DataType.TRANSACTION_RECOVERY) : - FetchDataFlow(requests, otherSide, dataType) { - - override fun load(txid: SecureHash): SignedTransactionWithStatus? = serviceHub.validatedTransactions.getTransactionWithStatus(txid) -} - -class FetchBatchTransactionsFlow(requests: Set, otherSide: FlowSession) : - FetchDataFlow(requests, otherSide, DataType.BATCH_TRANSACTION) { +class FetchBatchTransactionsFlow(requests: Set, otherSide: FlowSession, private val recoveryMode: Boolean = false) : + FetchDataFlow(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/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/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(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 0000000000..8da04d34d3 Binary files /dev/null and b/serialization/src/test/resources/net/corda/serialization/internal/amqp/EvolvabilityTests.maybeSerializedTransaction differ 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