mirror of
https://github.com/corda/corda.git
synced 2024-12-18 20:47:57 +00:00
Merge branch 'release/os/4.11' into merge-release/os/4.10-release/os/4.11-2023-10-17-7
This commit is contained in:
commit
0befdd6ebb
@ -1798,6 +1798,8 @@ 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.SecureHash, net.corda.core.crypto.TransactionSignature)
|
||||||
public static final boolean doVerify(net.corda.core.crypto.SignatureScheme, java.security.PublicKey, byte[], byte[])
|
public static final boolean doVerify(net.corda.core.crypto.SignatureScheme, java.security.PublicKey, byte[], byte[])
|
||||||
@NotNull
|
@NotNull
|
||||||
|
public static final byte[] encodePublicKey(java.security.PublicKey)
|
||||||
|
@NotNull
|
||||||
public static final java.security.Provider findProvider(String)
|
public static final java.security.Provider findProvider(String)
|
||||||
@NotNull
|
@NotNull
|
||||||
public static final net.corda.core.crypto.SignatureScheme findSignatureScheme(int)
|
public static final net.corda.core.crypto.SignatureScheme findSignatureScheme(int)
|
||||||
@ -2518,12 +2520,16 @@ public static final class net.corda.core.flows.ContractUpgradeFlow$Initiate exte
|
|||||||
protected net.corda.core.flows.AbstractStateReplacementFlow$UpgradeTx assembleTx()
|
protected net.corda.core.flows.AbstractStateReplacementFlow$UpgradeTx assembleTx()
|
||||||
##
|
##
|
||||||
public class net.corda.core.flows.DataVendingFlow extends net.corda.core.flows.FlowLogic
|
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)
|
||||||
|
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
|
@Suspendable
|
||||||
@Nullable
|
@Nullable
|
||||||
public Void call()
|
public Void call()
|
||||||
@NotNull
|
@NotNull
|
||||||
public final net.corda.core.flows.FlowSession getOtherSideSession()
|
public final java.util.Set<net.corda.core.flows.FlowSession> getOtherSessions()
|
||||||
@NotNull
|
@NotNull
|
||||||
public final Object getPayload()
|
public final Object getPayload()
|
||||||
@Suspendable
|
@Suspendable
|
||||||
@ -2535,10 +2541,61 @@ public class net.corda.core.flows.DataVendingFlow extends net.corda.core.flows.F
|
|||||||
@DoNotImplement
|
@DoNotImplement
|
||||||
public interface net.corda.core.flows.Destination
|
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
|
@InitiatingFlow
|
||||||
public final class net.corda.core.flows.FinalityFlow extends net.corda.core.flows.FlowLogic
|
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)
|
||||||
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>)
|
||||||
|
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>, 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)
|
||||||
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)
|
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)
|
||||||
@ -2570,12 +2627,32 @@ public static final class net.corda.core.flows.FinalityFlow$Companion$BROADCASTI
|
|||||||
public static final net.corda.core.flows.FinalityFlow$Companion$BROADCASTING INSTANCE
|
public static final net.corda.core.flows.FinalityFlow$Companion$BROADCASTING INSTANCE
|
||||||
##
|
##
|
||||||
@CordaSerializable
|
@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
|
public static final class net.corda.core.flows.FinalityFlow$Companion$NOTARISING extends net.corda.core.utilities.ProgressTracker$Step
|
||||||
@NotNull
|
@NotNull
|
||||||
public net.corda.core.utilities.ProgressTracker childProgressTracker()
|
public net.corda.core.utilities.ProgressTracker childProgressTracker()
|
||||||
public static final net.corda.core.flows.FinalityFlow$Companion$NOTARISING INSTANCE
|
public static final net.corda.core.flows.FinalityFlow$Companion$NOTARISING INSTANCE
|
||||||
##
|
##
|
||||||
@CordaSerializable
|
@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 class net.corda.core.flows.FlowException extends net.corda.core.CordaException implements net.corda.core.flows.IdentifiableException
|
||||||
public <init>()
|
public <init>()
|
||||||
public <init>(String)
|
public <init>(String)
|
||||||
@ -2877,6 +2954,37 @@ public static final class net.corda.core.flows.FlowStackSnapshot$Frame extends j
|
|||||||
public String toString()
|
public String toString()
|
||||||
##
|
##
|
||||||
@CordaSerializable
|
@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 class net.corda.core.flows.HospitalizeFlowException extends net.corda.core.CordaRuntimeException
|
||||||
public <init>()
|
public <init>()
|
||||||
public <init>(String)
|
public <init>(String)
|
||||||
@ -3138,6 +3246,10 @@ 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 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 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 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)
|
||||||
public <init>(net.corda.core.flows.FlowSession, net.corda.core.crypto.SecureHash)
|
public <init>(net.corda.core.flows.FlowSession, net.corda.core.crypto.SecureHash)
|
||||||
@ -3165,6 +3277,41 @@ public class net.corda.core.flows.ReceiveTransactionFlow extends net.corda.core.
|
|||||||
protected void checkBeforeRecording(net.corda.core.transactions.SignedTransaction)
|
protected void checkBeforeRecording(net.corda.core.transactions.SignedTransaction)
|
||||||
##
|
##
|
||||||
@CordaSerializable
|
@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 final class net.corda.core.flows.ResultSerializationException extends net.corda.core.CordaRuntimeException
|
||||||
public <init>(net.corda.core.serialization.internal.MissingSerializerException)
|
public <init>(net.corda.core.serialization.internal.MissingSerializerException)
|
||||||
##
|
##
|
||||||
@ -3175,6 +3322,12 @@ 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 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 <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 abstract class net.corda.core.flows.SignTransactionFlow extends net.corda.core.flows.FlowLogic
|
||||||
public <init>(net.corda.core.flows.FlowSession)
|
public <init>(net.corda.core.flows.FlowSession)
|
||||||
@ -3282,6 +3435,29 @@ public class net.corda.core.flows.StateReplacementException extends net.corda.co
|
|||||||
public <init>(String, Throwable, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
public <init>(String, Throwable, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||||
##
|
##
|
||||||
@CordaSerializable
|
@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 final class net.corda.core.flows.UnexpectedFlowEndException extends net.corda.core.CordaRuntimeException implements net.corda.core.flows.IdentifiableException
|
||||||
public <init>(String)
|
public <init>(String)
|
||||||
public <init>(String, Throwable)
|
public <init>(String, Throwable)
|
||||||
@ -4141,6 +4317,7 @@ public interface net.corda.core.node.ServicesForResolution
|
|||||||
@NotNull
|
@NotNull
|
||||||
public net.corda.core.transactions.LedgerTransaction specialise(net.corda.core.transactions.LedgerTransaction)
|
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 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 valueOf(String)
|
||||||
public static net.corda.core.node.StatesToRecord[] values()
|
public static net.corda.core.node.StatesToRecord[] values()
|
||||||
@ -4474,6 +4651,8 @@ public static final class net.corda.core.node.services.Vault$ConstraintInfo$Type
|
|||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
public static final class net.corda.core.node.services.Vault$Page extends java.lang.Object
|
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<?>)
|
||||||
|
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
|
@NotNull
|
||||||
public final java.util.List<net.corda.core.contracts.StateAndRef<T>> component1()
|
public final java.util.List<net.corda.core.contracts.StateAndRef<T>> component1()
|
||||||
@NotNull
|
@NotNull
|
||||||
@ -4483,11 +4662,17 @@ public static final class net.corda.core.node.services.Vault$Page extends java.l
|
|||||||
public final net.corda.core.node.services.Vault$StateStatus component4()
|
public final net.corda.core.node.services.Vault$StateStatus component4()
|
||||||
@NotNull
|
@NotNull
|
||||||
public final java.util.List<Object> component5()
|
public final java.util.List<Object> component5()
|
||||||
|
@Nullable
|
||||||
|
public final net.corda.core.contracts.StateRef component6()
|
||||||
@NotNull
|
@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<?>)
|
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)
|
public boolean equals(Object)
|
||||||
@NotNull
|
@NotNull
|
||||||
public final java.util.List<Object> getOtherResults()
|
public final java.util.List<Object> getOtherResults()
|
||||||
|
@Nullable
|
||||||
|
public final net.corda.core.contracts.StateRef getPreviousPageAnchor()
|
||||||
@NotNull
|
@NotNull
|
||||||
public final net.corda.core.node.services.Vault$StateStatus getStateTypes()
|
public final net.corda.core.node.services.Vault$StateStatus getStateTypes()
|
||||||
@NotNull
|
@NotNull
|
||||||
@ -8380,10 +8565,12 @@ public final class net.corda.testing.driver.DriverParameters extends java.lang.O
|
|||||||
public <init>(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, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
public <init>(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, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||||
public <init>(boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map<String, String>, boolean, boolean, boolean, java.util.List<net.corda.testing.node.NotarySpec>, java.util.List<String>, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Map<String, ?>, boolean, java.util.Collection<? extends net.corda.testing.node.TestCordapp>)
|
public <init>(boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map<String, String>, boolean, boolean, boolean, java.util.List<net.corda.testing.node.NotarySpec>, java.util.List<String>, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Map<String, ?>, boolean, java.util.Collection<? extends net.corda.testing.node.TestCordapp>)
|
||||||
public <init>(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, java.util.Collection, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
public <init>(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, java.util.Collection, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||||
public <init>(boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map<String, String>, boolean, boolean, boolean, java.util.List<net.corda.testing.node.NotarySpec>, java.util.List<String>, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Map<String, ?>, boolean, java.util.Collection<? extends net.corda.testing.node.TestCordapp>, java.nio.file.Path, java.util.List<? extends java.nio.file.Path>, java.util.Map<String, String>, boolean)
|
public <init>(boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map<String, String>, boolean, boolean, boolean, java.util.List<net.corda.testing.node.NotarySpec>, java.util.List<String>, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Map<String, ?>, boolean, java.util.Collection<? extends net.corda.testing.node.TestCordapp>, java.util.Map<String, String>, boolean)
|
||||||
public <init>(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, java.util.Collection, java.nio.file.Path, java.util.List, java.util.Map, boolean, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
public <init>(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, java.util.Collection, java.util.Map, boolean, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||||
public <init>(boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map<String, String>, boolean, boolean, boolean, java.util.List<net.corda.testing.node.NotarySpec>, java.util.List<String>, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Map<String, ?>, boolean, java.util.Collection<? extends net.corda.testing.node.TestCordapp>, java.nio.file.Path, java.util.List<? extends java.nio.file.Path>, java.util.Map<String, String>, boolean, boolean)
|
public <init>(boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map<String, String>, boolean, boolean, boolean, java.util.List<net.corda.testing.node.NotarySpec>, java.util.List<String>, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Map<String, ?>, boolean, java.util.Collection<? extends net.corda.testing.node.TestCordapp>, java.util.Map<String, String>, boolean, boolean)
|
||||||
public <init>(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, java.util.Collection, java.nio.file.Path, java.util.List, java.util.Map, boolean, boolean, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
public <init>(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, java.util.Collection, java.util.Map, boolean, boolean, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||||
|
public <init>(boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map<String, String>, boolean, boolean, boolean, java.util.List<net.corda.testing.node.NotarySpec>, java.util.List<String>, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Map<String, ?>, boolean, java.util.Collection<? extends net.corda.testing.node.TestCordapp>, java.util.Map<String, String>, boolean, boolean, java.time.Duration)
|
||||||
|
public <init>(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, java.util.Collection, java.util.Map, boolean, boolean, java.time.Duration, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||||
public <init>(boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map<String, String>, boolean, boolean, boolean, java.util.List<net.corda.testing.node.NotarySpec>, java.util.List<String>, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, boolean)
|
public <init>(boolean, java.nio.file.Path, net.corda.testing.driver.PortAllocation, net.corda.testing.driver.PortAllocation, java.util.Map<String, String>, boolean, boolean, boolean, java.util.List<net.corda.testing.node.NotarySpec>, java.util.List<String>, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, boolean)
|
||||||
public final boolean component1()
|
public final boolean component1()
|
||||||
@NotNull
|
@NotNull
|
||||||
@ -8397,16 +8584,14 @@ public final class net.corda.testing.driver.DriverParameters extends java.lang.O
|
|||||||
public final boolean component14()
|
public final boolean component14()
|
||||||
@Nullable
|
@Nullable
|
||||||
public final java.util.Collection<net.corda.testing.node.TestCordapp> component15()
|
public final java.util.Collection<net.corda.testing.node.TestCordapp> component15()
|
||||||
@Nullable
|
|
||||||
public final java.nio.file.Path component16()
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public final java.util.List<java.nio.file.Path> component17()
|
public final java.util.Map<String, String> component16()
|
||||||
|
public final boolean component17()
|
||||||
|
public final boolean component18()
|
||||||
@NotNull
|
@NotNull
|
||||||
public final java.util.Map<String, String> component18()
|
public final java.time.Duration component19()
|
||||||
public final boolean component19()
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public final java.nio.file.Path component2()
|
public final java.nio.file.Path component2()
|
||||||
public final boolean component20()
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public final net.corda.testing.driver.PortAllocation component3()
|
public final net.corda.testing.driver.PortAllocation component3()
|
||||||
@NotNull
|
@NotNull
|
||||||
@ -8423,9 +8608,11 @@ public final class net.corda.testing.driver.DriverParameters extends java.lang.O
|
|||||||
@NotNull
|
@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<String, String>, boolean, boolean, boolean, java.util.List<net.corda.testing.node.NotarySpec>, java.util.List<String>, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Map<String, ?>, boolean, java.util.Collection<? extends net.corda.testing.node.TestCordapp>)
|
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<String, String>, boolean, boolean, boolean, java.util.List<net.corda.testing.node.NotarySpec>, java.util.List<String>, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Map<String, ?>, boolean, java.util.Collection<? extends net.corda.testing.node.TestCordapp>)
|
||||||
@NotNull
|
@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<String, String>, boolean, boolean, boolean, java.util.List<net.corda.testing.node.NotarySpec>, java.util.List<String>, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Map<String, ?>, boolean, java.util.Collection<? extends net.corda.testing.node.TestCordapp>, java.nio.file.Path, java.util.List<? extends java.nio.file.Path>, java.util.Map<String, String>, boolean)
|
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<String, String>, boolean, boolean, boolean, java.util.List<net.corda.testing.node.NotarySpec>, java.util.List<String>, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Map<String, ?>, boolean, java.util.Collection<? extends net.corda.testing.node.TestCordapp>, java.util.Map<String, String>, boolean)
|
||||||
@NotNull
|
@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<String, String>, boolean, boolean, boolean, java.util.List<net.corda.testing.node.NotarySpec>, java.util.List<String>, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Map<String, ?>, boolean, java.util.Collection<? extends net.corda.testing.node.TestCordapp>, java.nio.file.Path, java.util.List<? extends java.nio.file.Path>, java.util.Map<String, String>, boolean, boolean)
|
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<String, String>, boolean, boolean, boolean, java.util.List<net.corda.testing.node.NotarySpec>, java.util.List<String>, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Map<String, ?>, boolean, java.util.Collection<? extends net.corda.testing.node.TestCordapp>, java.util.Map<String, String>, boolean, 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<String, String>, boolean, boolean, boolean, java.util.List<net.corda.testing.node.NotarySpec>, java.util.List<String>, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Map<String, ?>, boolean, java.util.Collection<? extends net.corda.testing.node.TestCordapp>, java.util.Map<String, String>, boolean, boolean, java.time.Duration)
|
||||||
@NotNull
|
@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<String, String>, boolean, boolean, boolean, java.util.List<net.corda.testing.node.NotarySpec>, java.util.List<String>, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Set<? extends net.corda.testing.node.TestCordapp>)
|
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<String, String>, boolean, boolean, boolean, java.util.List<net.corda.testing.node.NotarySpec>, java.util.List<String>, net.corda.testing.driver.JmxPolicy, net.corda.core.node.NetworkParameters, java.util.Set<? extends net.corda.testing.node.TestCordapp>)
|
||||||
public boolean equals(Object)
|
public boolean equals(Object)
|
||||||
@ -8434,10 +8621,6 @@ public final class net.corda.testing.driver.DriverParameters extends java.lang.O
|
|||||||
public final java.util.Collection<net.corda.testing.node.TestCordapp> getCordappsForAllNodes()
|
public final java.util.Collection<net.corda.testing.node.TestCordapp> getCordappsForAllNodes()
|
||||||
@NotNull
|
@NotNull
|
||||||
public final net.corda.testing.driver.PortAllocation getDebugPortAllocation()
|
public final net.corda.testing.driver.PortAllocation getDebugPortAllocation()
|
||||||
@Nullable
|
|
||||||
public final java.nio.file.Path getDjvmBootstrapSource()
|
|
||||||
@NotNull
|
|
||||||
public final java.util.List<java.nio.file.Path> getDjvmCordaSource()
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public final java.nio.file.Path getDriverDirectory()
|
public final java.nio.file.Path getDriverDirectory()
|
||||||
@NotNull
|
@NotNull
|
||||||
@ -8452,6 +8635,8 @@ public final class net.corda.testing.driver.DriverParameters extends java.lang.O
|
|||||||
@NotNull
|
@NotNull
|
||||||
public final java.util.Map<String, Object> getNotaryCustomOverrides()
|
public final java.util.Map<String, Object> getNotaryCustomOverrides()
|
||||||
@NotNull
|
@NotNull
|
||||||
|
public final java.time.Duration getNotaryHandleTimeout()
|
||||||
|
@NotNull
|
||||||
public final java.util.List<net.corda.testing.node.NotarySpec> getNotarySpecs()
|
public final java.util.List<net.corda.testing.node.NotarySpec> getNotarySpecs()
|
||||||
@NotNull
|
@NotNull
|
||||||
public final net.corda.testing.driver.PortAllocation getPortAllocation()
|
public final net.corda.testing.driver.PortAllocation getPortAllocation()
|
||||||
@ -8472,10 +8657,6 @@ public final class net.corda.testing.driver.DriverParameters extends java.lang.O
|
|||||||
@NotNull
|
@NotNull
|
||||||
public final net.corda.testing.driver.DriverParameters withDebugPortAllocation(net.corda.testing.driver.PortAllocation)
|
public final net.corda.testing.driver.DriverParameters withDebugPortAllocation(net.corda.testing.driver.PortAllocation)
|
||||||
@NotNull
|
@NotNull
|
||||||
public final net.corda.testing.driver.DriverParameters withDjvmBootstrapSource(java.nio.file.Path)
|
|
||||||
@NotNull
|
|
||||||
public final net.corda.testing.driver.DriverParameters withDjvmCordaSource(java.util.List<? extends java.nio.file.Path>)
|
|
||||||
@NotNull
|
|
||||||
public final net.corda.testing.driver.DriverParameters withDriverDirectory(java.nio.file.Path)
|
public final net.corda.testing.driver.DriverParameters withDriverDirectory(java.nio.file.Path)
|
||||||
@NotNull
|
@NotNull
|
||||||
public final net.corda.testing.driver.DriverParameters withEnvironmentVariables(java.util.Map<String, String>)
|
public final net.corda.testing.driver.DriverParameters withEnvironmentVariables(java.util.Map<String, String>)
|
||||||
@ -8492,6 +8673,8 @@ public final class net.corda.testing.driver.DriverParameters extends java.lang.O
|
|||||||
@NotNull
|
@NotNull
|
||||||
public final net.corda.testing.driver.DriverParameters withNotaryCustomOverrides(java.util.Map<String, ?>)
|
public final net.corda.testing.driver.DriverParameters withNotaryCustomOverrides(java.util.Map<String, ?>)
|
||||||
@NotNull
|
@NotNull
|
||||||
|
public final net.corda.testing.driver.DriverParameters withNotaryHandleTimeout(java.time.Duration)
|
||||||
|
@NotNull
|
||||||
public final net.corda.testing.driver.DriverParameters withNotarySpecs(java.util.List<net.corda.testing.node.NotarySpec>)
|
public final net.corda.testing.driver.DriverParameters withNotarySpecs(java.util.List<net.corda.testing.node.NotarySpec>)
|
||||||
@NotNull
|
@NotNull
|
||||||
public final net.corda.testing.driver.DriverParameters withPortAllocation(net.corda.testing.driver.PortAllocation)
|
public final net.corda.testing.driver.DriverParameters withPortAllocation(net.corda.testing.driver.PortAllocation)
|
||||||
@ -8724,6 +8907,7 @@ 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<?>>...)
|
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
|
@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 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
|
@DoNotImplement
|
||||||
public abstract class net.corda.testing.node.ClusterSpec extends java.lang.Object
|
public abstract class net.corda.testing.node.ClusterSpec extends java.lang.Object
|
||||||
@ -9145,7 +9329,9 @@ public class net.corda.testing.node.MockServices extends java.lang.Object implem
|
|||||||
@NotNull
|
@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 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 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 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(net.corda.core.transactions.SignedTransaction, net.corda.core.transactions.SignedTransaction...)
|
||||||
public void recordTransactions(boolean, Iterable<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...)
|
public void recordTransactions(boolean, net.corda.core.transactions.SignedTransaction, net.corda.core.transactions.SignedTransaction...)
|
||||||
|
4
.ci/dev/forward-merge/Jenkinsfile
vendored
4
.ci/dev/forward-merge/Jenkinsfile
vendored
@ -13,13 +13,13 @@
|
|||||||
* the branch name of origin branch, it should match the current branch
|
* the branch name of origin branch, it should match the current branch
|
||||||
* and it acts as a fail-safe inside {@code forwardMerger} pipeline
|
* and it acts as a fail-safe inside {@code forwardMerger} pipeline
|
||||||
*/
|
*/
|
||||||
String originBranch = 'release/os/4.10'
|
String originBranch = 'release/os/4.11'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the branch name of target branch, it should be the branch with the next version
|
* the branch name of target branch, it should be the branch with the next version
|
||||||
* after the one in current branch.
|
* after the one in current branch.
|
||||||
*/
|
*/
|
||||||
String targetBranch = 'release/os/4.11'
|
String targetBranch = 'release/os/4.12'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forward merge any changes between #originBranch and #targetBranch
|
* Forward merge any changes between #originBranch and #targetBranch
|
||||||
|
1
.ci/dev/pr-code-checks/Jenkinsfile
vendored
1
.ci/dev/pr-code-checks/Jenkinsfile
vendored
@ -53,6 +53,7 @@ pipeline {
|
|||||||
steps {
|
steps {
|
||||||
authenticateGradleWrapper()
|
authenticateGradleWrapper()
|
||||||
sh 'mkdir -p ${GRADLE_USER_HOME}'
|
sh 'mkdir -p ${GRADLE_USER_HOME}'
|
||||||
|
authenticateGradleWrapper()
|
||||||
snykDeltaScan(env.SNYK_API_TOKEN, env.C4_OS_SNYK_ORG_ID)
|
snykDeltaScan(env.SNYK_API_TOKEN, env.C4_OS_SNYK_ORG_ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
8
.github/CODEOWNERS
vendored
8
.github/CODEOWNERS
vendored
@ -7,14 +7,6 @@ node-api @rick-r3
|
|||||||
node/src/main/kotlin/net/corda/node/internal @rick-r3
|
node/src/main/kotlin/net/corda/node/internal @rick-r3
|
||||||
node/src/main/kotlin/net/corda/node/services @rick-r3
|
node/src/main/kotlin/net/corda/node/services @rick-r3
|
||||||
|
|
||||||
# Determinstic components
|
|
||||||
core-deterministic @rick-r3
|
|
||||||
jdk8u-deterministic @rick-r3
|
|
||||||
node/djvm @rick-r3
|
|
||||||
serialization-deterministic @rick-r3
|
|
||||||
serialization-djvm @rick-r3
|
|
||||||
serialization-tests @rick-r3
|
|
||||||
|
|
||||||
# Demobench defaults to Chris, but Viktor for the main code
|
# Demobench defaults to Chris, but Viktor for the main code
|
||||||
tools/demobench @rick-r3
|
tools/demobench @rick-r3
|
||||||
|
|
||||||
|
2
.github/workflows/check-pr-title.yml
vendored
2
.github/workflows/check-pr-title.yml
vendored
@ -9,6 +9,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: morrisoncole/pr-lint-action@v1.6.1
|
- uses: morrisoncole/pr-lint-action@v1.6.1
|
||||||
with:
|
with:
|
||||||
title-regex: '^((CORDA|AG|EG|ENT|INFRA|ES)-\d+|NOTICK)(.*)'
|
title-regex: '^((CORDA|AG|EG|ENT|INFRA|ES)-\d+)(.*)'
|
||||||
on-failed-regex-comment: "PR title failed to match regex -> `%regex%`"
|
on-failed-regex-comment: "PR title failed to match regex -> `%regex%`"
|
||||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||||
|
37
build.gradle
37
build.gradle
@ -75,8 +75,6 @@ buildscript {
|
|||||||
ext.disruptor_version = constants.getProperty("disruptorVersion")
|
ext.disruptor_version = constants.getProperty("disruptorVersion")
|
||||||
ext.metrics_version = constants.getProperty("metricsVersion")
|
ext.metrics_version = constants.getProperty("metricsVersion")
|
||||||
ext.metrics_new_relic_version = constants.getProperty("metricsNewRelicVersion")
|
ext.metrics_new_relic_version = constants.getProperty("metricsNewRelicVersion")
|
||||||
ext.djvm_version = constants.getProperty("djvmVersion")
|
|
||||||
ext.deterministic_rt_version = constants.getProperty('deterministicRtVersion')
|
|
||||||
ext.okhttp_version = constants.getProperty("okhttpVersion")
|
ext.okhttp_version = constants.getProperty("okhttpVersion")
|
||||||
ext.netty_version = constants.getProperty("nettyVersion")
|
ext.netty_version = constants.getProperty("nettyVersion")
|
||||||
ext.tcnative_version = constants.getProperty("tcnativeVersion")
|
ext.tcnative_version = constants.getProperty("tcnativeVersion")
|
||||||
@ -134,9 +132,6 @@ buildscript {
|
|||||||
ext.fontawesomefx_fontawesome_version = constants.getProperty("fontawesomefxFontawesomeVersion")
|
ext.fontawesomefx_fontawesome_version = constants.getProperty("fontawesomefxFontawesomeVersion")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name of the IntelliJ SDK created for the deterministic Java rt.jar.
|
|
||||||
// ext.deterministic_idea_sdk = '1.8 (Deterministic)'
|
|
||||||
|
|
||||||
// Update 121 is required for ObjectInputFilter.
|
// Update 121 is required for ObjectInputFilter.
|
||||||
// Updates [131, 161] also have zip compression bugs on MacOS (High Sierra).
|
// Updates [131, 161] also have zip compression bugs on MacOS (High Sierra).
|
||||||
// when the java version in NodeStartup.hasMinimumJavaVersion() changes, so must this check
|
// when the java version in NodeStartup.hasMinimumJavaVersion() changes, so must this check
|
||||||
@ -581,28 +576,6 @@ task jacocoRootReport(type: org.gradle.testing.jacoco.tasks.JacocoReport) {
|
|||||||
it.exists()
|
it.exists()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
afterEvaluate {
|
|
||||||
classDirectories = files(classDirectories.files.collect {
|
|
||||||
fileTree(dir: it,
|
|
||||||
// these exclusions are necessary because jacoco gets confused by same class names
|
|
||||||
// which occur due to deterministic versions of non deterministic classes
|
|
||||||
exclude: ['**/net/corda/core/crypto/DigestSupplier**',
|
|
||||||
'**/net/corda/core/crypto/DelegatingSecureRandomService',
|
|
||||||
'**/net/corda/core/internal/ThreadLocalToggleField**',
|
|
||||||
'**/net/corda/core/internal/InheritableThreadLocalToggleField**',
|
|
||||||
'**/net/corda/core/internal/ToggleField**',
|
|
||||||
'net/corda/core/internal/rules/StateContractValidationEnforcementRule**',
|
|
||||||
'net/corda/core/internal/SimpleToggleField**',
|
|
||||||
'net/corda/core/serialization/SerializationFactory**',
|
|
||||||
'net/corda/serialization/internal/amqp/AMQPStreams**',
|
|
||||||
'net/corda/serialization/internal/amqp/AMQPSerializerFactories**',
|
|
||||||
'net/corda/serialization/internal/amqp/AMQPSerializationThreadContext**',
|
|
||||||
'net/corda/serialization/internal/ByteBufferStreams**',
|
|
||||||
'net/corda/serialization/internal/model/DefaultCacheProvider**',
|
|
||||||
'net/corda/serialization/internal/DefaultWhitelist**'
|
|
||||||
])
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('detekt', JavaExec) {
|
tasks.register('detekt', JavaExec) {
|
||||||
@ -655,15 +628,11 @@ bintrayConfig {
|
|||||||
'corda-mock',
|
'corda-mock',
|
||||||
'corda-rpc',
|
'corda-rpc',
|
||||||
'corda-core',
|
'corda-core',
|
||||||
'corda-core-deterministic',
|
|
||||||
'corda-deterministic-verifier',
|
|
||||||
'corda-deserializers-djvm',
|
|
||||||
'corda',
|
'corda',
|
||||||
'corda-finance-workflows',
|
'corda-finance-workflows',
|
||||||
'corda-finance-contracts',
|
'corda-finance-contracts',
|
||||||
'corda-node',
|
'corda-node',
|
||||||
'corda-node-api',
|
'corda-node-api',
|
||||||
'corda-node-djvm',
|
|
||||||
'corda-test-common',
|
'corda-test-common',
|
||||||
'corda-core-test-utils',
|
'corda-core-test-utils',
|
||||||
'corda-test-utils',
|
'corda-test-utils',
|
||||||
@ -676,8 +645,6 @@ bintrayConfig {
|
|||||||
'corda-shell',
|
'corda-shell',
|
||||||
'corda-tools-shell-cli',
|
'corda-tools-shell-cli',
|
||||||
'corda-serialization',
|
'corda-serialization',
|
||||||
'corda-serialization-deterministic',
|
|
||||||
'corda-serialization-djvm',
|
|
||||||
'corda-tools-blob-inspector',
|
'corda-tools-blob-inspector',
|
||||||
'corda-tools-explorer',
|
'corda-tools-explorer',
|
||||||
'corda-tools-network-bootstrapper',
|
'corda-tools-network-bootstrapper',
|
||||||
@ -808,8 +775,4 @@ distributedTesting {
|
|||||||
distribution DistributeTestsBy.METHOD
|
distribution DistributeTestsBy.METHOD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ignoredTests = [
|
|
||||||
':core-deterministic:testing:data:test'
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
@ -9,4 +9,4 @@ package net.corda.common.logging
|
|||||||
* (originally added to source control for ease of use)
|
* (originally added to source control for ease of use)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
internal const val CURRENT_MAJOR_RELEASE = "4.10-SNAPSHOT"
|
internal const val CURRENT_MAJOR_RELEASE = "4.11-SNAPSHOT"
|
@ -3,7 +3,7 @@
|
|||||||
# their own projects. So don't get fancy with syntax!
|
# their own projects. So don't get fancy with syntax!
|
||||||
# Fancy syntax - multi pass ${whatever} replacement
|
# Fancy syntax - multi pass ${whatever} replacement
|
||||||
|
|
||||||
cordaVersion=4.10
|
cordaVersion=4.11
|
||||||
versionSuffix=SNAPSHOT
|
versionSuffix=SNAPSHOT
|
||||||
gradlePluginsVersion=5.0.12
|
gradlePluginsVersion=5.0.12
|
||||||
kotlinVersion=1.2.71
|
kotlinVersion=1.2.71
|
||||||
@ -12,7 +12,7 @@ java8MinUpdateVersion=171
|
|||||||
# When incrementing platformVersion make sure to update #
|
# When incrementing platformVersion make sure to update #
|
||||||
# net.corda.core.internal.CordaUtilsKt.PLATFORM_VERSION as well. #
|
# net.corda.core.internal.CordaUtilsKt.PLATFORM_VERSION as well. #
|
||||||
# ***************************************************************#
|
# ***************************************************************#
|
||||||
platformVersion=12
|
platformVersion=13
|
||||||
openTelemetryVersion=1.20.1
|
openTelemetryVersion=1.20.1
|
||||||
openTelemetrySemConvVersion=1.20.1-alpha
|
openTelemetrySemConvVersion=1.20.1-alpha
|
||||||
guavaVersion=28.0-jre
|
guavaVersion=28.0-jre
|
||||||
@ -24,7 +24,7 @@ jdkClassifier11=jdk11
|
|||||||
dockerJavaVersion=3.2.5
|
dockerJavaVersion=3.2.5
|
||||||
proguardVersion=6.1.1
|
proguardVersion=6.1.1
|
||||||
// bouncy castle version must not be changed on a patch release. Needs a full release test cycle to flush out any issues.
|
// bouncy castle version must not be changed on a patch release. Needs a full release test cycle to flush out any issues.
|
||||||
bouncycastleVersion=1.70
|
bouncycastleVersion=1.75
|
||||||
classgraphVersion=4.8.135
|
classgraphVersion=4.8.135
|
||||||
disruptorVersion=3.4.2
|
disruptorVersion=3.4.2
|
||||||
typesafeConfigVersion=1.3.4
|
typesafeConfigVersion=1.3.4
|
||||||
@ -34,8 +34,6 @@ snakeYamlVersion=1.33
|
|||||||
caffeineVersion=2.9.3
|
caffeineVersion=2.9.3
|
||||||
metricsVersion=4.1.0
|
metricsVersion=4.1.0
|
||||||
metricsNewRelicVersion=1.1.1
|
metricsNewRelicVersion=1.1.1
|
||||||
djvmVersion=1.1.1
|
|
||||||
deterministicRtVersion=1.0-RC02
|
|
||||||
openSourceBranch=https://github.com/corda/corda/blob/release/os/4.4
|
openSourceBranch=https://github.com/corda/corda/blob/release/os/4.4
|
||||||
openSourceSamplesBranch=https://github.com/corda/samples/blob/release-V4
|
openSourceSamplesBranch=https://github.com/corda/samples/blob/release-V4
|
||||||
jolokiaAgentVersion=1.6.1
|
jolokiaAgentVersion=1.6.1
|
||||||
@ -78,9 +76,9 @@ mockitoKotlinVersion=1.6.0
|
|||||||
hamkrestVersion=1.7.0.0
|
hamkrestVersion=1.7.0.0
|
||||||
joptSimpleVersion=5.0.2
|
joptSimpleVersion=5.0.2
|
||||||
jansiVersion=1.18
|
jansiVersion=1.18
|
||||||
hibernateVersion=5.4.32.Final
|
hibernateVersion=5.6.14.Final
|
||||||
# h2Version - Update docs if renamed or removed.
|
# h2Version - Update docs if renamed or removed.
|
||||||
h2Version=1.4.199
|
h2Version=2.1.214
|
||||||
rxjavaVersion=1.3.8
|
rxjavaVersion=1.3.8
|
||||||
dokkaVersion=0.10.1
|
dokkaVersion=0.10.1
|
||||||
eddsaVersion=0.3.0
|
eddsaVersion=0.3.0
|
||||||
@ -89,7 +87,7 @@ commonsCollectionsVersion=4.3
|
|||||||
beanutilsVersion=1.9.4
|
beanutilsVersion=1.9.4
|
||||||
shiroVersion=1.10.0
|
shiroVersion=1.10.0
|
||||||
hikariVersion=3.3.1
|
hikariVersion=3.3.1
|
||||||
liquibaseVersion=3.6.3
|
liquibaseVersion=4.20.0
|
||||||
dockerComposeRuleVersion=1.5.0
|
dockerComposeRuleVersion=1.5.0
|
||||||
seleniumVersion=3.141.59
|
seleniumVersion=3.141.59
|
||||||
ghostdriverVersion=2.1.0
|
ghostdriverVersion=2.1.0
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
## corda-core-deterministic.
|
|
||||||
This artifact is a deterministic subset of the binary contents of `corda-core`.
|
|
@ -1,245 +0,0 @@
|
|||||||
import net.corda.gradle.jarfilter.JarFilterTask
|
|
||||||
import net.corda.gradle.jarfilter.MetaFixerTask
|
|
||||||
import proguard.gradle.ProGuardTask
|
|
||||||
|
|
||||||
import static org.gradle.api.JavaVersion.VERSION_1_8
|
|
||||||
|
|
||||||
plugins {
|
|
||||||
id 'org.jetbrains.kotlin.jvm'
|
|
||||||
id 'net.corda.plugins.publish-utils'
|
|
||||||
id 'com.jfrog.artifactory'
|
|
||||||
id 'java-library'
|
|
||||||
id 'idea'
|
|
||||||
}
|
|
||||||
apply from: "${rootProject.projectDir}/deterministic.gradle"
|
|
||||||
|
|
||||||
description 'Corda core (deterministic)'
|
|
||||||
|
|
||||||
evaluationDependsOn(":core")
|
|
||||||
|
|
||||||
// required by DJVM and Avian JVM (for running inside the SGX enclave) which only supports Java 8.
|
|
||||||
targetCompatibility = VERSION_1_8
|
|
||||||
|
|
||||||
def javaHome = System.getProperty('java.home')
|
|
||||||
def jarBaseName = "corda-${project.name}".toString()
|
|
||||||
|
|
||||||
configurations {
|
|
||||||
deterministicLibraries {
|
|
||||||
canBeConsumed = false
|
|
||||||
extendsFrom api
|
|
||||||
}
|
|
||||||
deterministicArtifacts.extendsFrom deterministicLibraries
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
compileOnly project(':core')
|
|
||||||
|
|
||||||
// Configure these by hand. It should be a minimal subset of core's dependencies,
|
|
||||||
// and without any obviously non-deterministic ones such as Hibernate.
|
|
||||||
|
|
||||||
// These "api" dependencies will become "compile" scoped in our published POM.
|
|
||||||
api "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
|
||||||
api "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
|
||||||
api "javax.persistence:javax.persistence-api:2.2"
|
|
||||||
api "com.google.code.findbugs:jsr305:$jsr305_version"
|
|
||||||
api "org.slf4j:slf4j-api:$slf4j_version"
|
|
||||||
|
|
||||||
compileOnly "io.opentelemetry:opentelemetry-api:${open_telemetry_version}"
|
|
||||||
compileOnly project(':opentelemetry')
|
|
||||||
|
|
||||||
// These dependencies will become "runtime" scoped in our published POM.
|
|
||||||
// See publish.dependenciesFrom.defaultScope.
|
|
||||||
deterministicLibraries "org.bouncycastle:bcprov-jdk15on:$bouncycastle_version"
|
|
||||||
deterministicLibraries "org.bouncycastle:bcpkix-jdk15on:$bouncycastle_version"
|
|
||||||
deterministicLibraries "net.i2p.crypto:eddsa:$eddsa_version"
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.named('jar', Jar) {
|
|
||||||
archiveBaseName = 'DOES-NOT-EXIST'
|
|
||||||
// Don't build a jar here because it would be the wrong one.
|
|
||||||
// The jar we really want will be built by the metafix task.
|
|
||||||
enabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
def coreJarTask = project(':core').tasks.named('jar', Jar)
|
|
||||||
def originalJar = coreJarTask.map { it.outputs.files.singleFile }
|
|
||||||
|
|
||||||
def patchCore = tasks.register('patchCore', Zip) {
|
|
||||||
dependsOn coreJarTask
|
|
||||||
destinationDirectory = layout.buildDirectory.dir('source-libs')
|
|
||||||
metadataCharset 'UTF-8'
|
|
||||||
archiveClassifier = 'transient'
|
|
||||||
archiveExtension = 'jar'
|
|
||||||
|
|
||||||
from(compileKotlin)
|
|
||||||
from(processResources)
|
|
||||||
from(zipTree(originalJar)) {
|
|
||||||
exclude 'net/corda/core/crypto/DelegatingSecureRandomService*.class'
|
|
||||||
exclude 'net/corda/core/crypto/DigestSupplier.class'
|
|
||||||
exclude 'net/corda/core/internal/*ToggleField*.class'
|
|
||||||
exclude 'net/corda/core/serialization/*SerializationFactory*.class'
|
|
||||||
exclude 'net/corda/core/serialization/internal/AttachmentsHolderImpl.class'
|
|
||||||
exclude 'net/corda/core/serialization/internal/CheckpointSerializationFactory*.class'
|
|
||||||
exclude 'net/corda/core/internal/rules/*.class'
|
|
||||||
exclude 'net/corda/core/internal/utilities/PrivateInterner*.class'
|
|
||||||
}
|
|
||||||
|
|
||||||
reproducibleFileOrder = true
|
|
||||||
includeEmptyDirs = false
|
|
||||||
}
|
|
||||||
|
|
||||||
def predeterminise = tasks.register('predeterminise', ProGuardTask) {
|
|
||||||
injars patchCore
|
|
||||||
outjars file("$buildDir/proguard/pre-deterministic-${project.version}.jar")
|
|
||||||
|
|
||||||
if (JavaVersion.current().isJava9Compatible()) {
|
|
||||||
libraryjars "$javaHome/jmods"
|
|
||||||
} else {
|
|
||||||
libraryjars "$javaHome/lib/rt.jar"
|
|
||||||
libraryjars "$javaHome/lib/jce.jar"
|
|
||||||
}
|
|
||||||
configurations.compileClasspath.forEach {
|
|
||||||
if (originalJar != it) {
|
|
||||||
libraryjars it, filter: '!META-INF/versions/**'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
keepattributes '*'
|
|
||||||
keepdirectories
|
|
||||||
dontwarn '**$1$1,org.hibernate.annotations.*'
|
|
||||||
dontpreverify
|
|
||||||
dontobfuscate
|
|
||||||
dontoptimize
|
|
||||||
dontnote
|
|
||||||
printseeds
|
|
||||||
verbose
|
|
||||||
|
|
||||||
keep '@interface net.corda.core.* { *; }'
|
|
||||||
keep '@interface net.corda.core.contracts.** { *; }'
|
|
||||||
keep '@interface net.corda.core.serialization.** { *; }'
|
|
||||||
keep '@net.corda.core.KeepForDJVM class * { *; }', includedescriptorclasses:true
|
|
||||||
keepclassmembers 'class net.corda.core.** { public synthetic <methods>; }'
|
|
||||||
}
|
|
||||||
|
|
||||||
def jarFilter = tasks.register('jarFilter', JarFilterTask) {
|
|
||||||
jars predeterminise
|
|
||||||
annotations {
|
|
||||||
forDelete = [
|
|
||||||
"net.corda.core.DeleteForDJVM"
|
|
||||||
]
|
|
||||||
forStub = [
|
|
||||||
"net.corda.core.StubOutForDJVM"
|
|
||||||
]
|
|
||||||
forRemove = [
|
|
||||||
"co.paralleluniverse.fibers.Suspendable",
|
|
||||||
"org.hibernate.annotations.Immutable"
|
|
||||||
]
|
|
||||||
forSanitise = [
|
|
||||||
"net.corda.core.DeleteForDJVM"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def determinise = tasks.register('determinise', ProGuardTask) {
|
|
||||||
injars jarFilter
|
|
||||||
outjars file("$buildDir/proguard/$jarBaseName-${project.version}.jar")
|
|
||||||
|
|
||||||
if (JavaVersion.current().isJava9Compatible()) {
|
|
||||||
libraryjars "$javaHome/jmods"
|
|
||||||
} else {
|
|
||||||
libraryjars "$javaHome/lib/rt.jar"
|
|
||||||
libraryjars "$javaHome/lib/jce.jar"
|
|
||||||
}
|
|
||||||
configurations.deterministicLibraries.forEach {
|
|
||||||
libraryjars it, filter: '!META-INF/versions/**'
|
|
||||||
}
|
|
||||||
|
|
||||||
// Analyse the JAR for dead code, and remove (some of) it.
|
|
||||||
optimizations 'code/removal/simple,code/removal/advanced'
|
|
||||||
printconfiguration
|
|
||||||
|
|
||||||
keepattributes '*'
|
|
||||||
keepdirectories
|
|
||||||
dontobfuscate
|
|
||||||
dontnote
|
|
||||||
printseeds
|
|
||||||
verbose
|
|
||||||
|
|
||||||
keep '@interface net.corda.core.CordaInternal { *; }'
|
|
||||||
keep '@interface net.corda.core.DoNotImplement { *; }'
|
|
||||||
keep '@interface net.corda.core.KeepForDJVM { *; }'
|
|
||||||
keep '@interface net.corda.core.contracts.** { *; }'
|
|
||||||
keep '@interface net.corda.core.serialization.** { *; }'
|
|
||||||
keep '@net.corda.core.KeepForDJVM class * { *; }', includedescriptorclasses:true
|
|
||||||
keepclassmembers 'class net.corda.core.** { public synthetic <methods>; }'
|
|
||||||
}
|
|
||||||
|
|
||||||
def checkDeterminism = tasks.register('checkDeterminism', ProGuardTask)
|
|
||||||
|
|
||||||
def metafix = tasks.register('metafix', MetaFixerTask) {
|
|
||||||
outputDir = layout.buildDirectory.dir('libs')
|
|
||||||
jars determinise
|
|
||||||
suffix ""
|
|
||||||
|
|
||||||
// Strip timestamps from the JAR to make it reproducible.
|
|
||||||
preserveTimestamps = false
|
|
||||||
finalizedBy checkDeterminism
|
|
||||||
}
|
|
||||||
|
|
||||||
// DOCSTART 01
|
|
||||||
checkDeterminism.configure {
|
|
||||||
dependsOn jdkTask
|
|
||||||
injars metafix
|
|
||||||
|
|
||||||
libraryjars deterministic_rt_jar
|
|
||||||
|
|
||||||
configurations.deterministicLibraries.forEach {
|
|
||||||
libraryjars it, filter: '!META-INF/versions/**'
|
|
||||||
}
|
|
||||||
|
|
||||||
keepattributes '*'
|
|
||||||
dontpreverify
|
|
||||||
dontobfuscate
|
|
||||||
dontoptimize
|
|
||||||
verbose
|
|
||||||
|
|
||||||
keep 'class *'
|
|
||||||
}
|
|
||||||
// DOCEND 01
|
|
||||||
|
|
||||||
defaultTasks "determinise"
|
|
||||||
determinise.configure {
|
|
||||||
finalizedBy metafix
|
|
||||||
}
|
|
||||||
tasks.named('assemble') {
|
|
||||||
dependsOn checkDeterminism
|
|
||||||
}
|
|
||||||
|
|
||||||
def deterministicJar = metafix.map { it.outputs.files.singleFile }
|
|
||||||
artifacts {
|
|
||||||
deterministicArtifacts deterministicJar
|
|
||||||
publish deterministicJar
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.named('sourceJar', Jar) {
|
|
||||||
from 'README.md'
|
|
||||||
include 'README.md'
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.named('javadocJar', Jar) {
|
|
||||||
from 'README.md'
|
|
||||||
include 'README.md'
|
|
||||||
}
|
|
||||||
|
|
||||||
publish {
|
|
||||||
dependenciesFrom configurations.deterministicArtifacts
|
|
||||||
name jarBaseName
|
|
||||||
}
|
|
||||||
|
|
||||||
idea {
|
|
||||||
module {
|
|
||||||
if (project.hasProperty("deterministic_idea_sdk")) {
|
|
||||||
jdkName project.property("deterministic_idea_sdk") as String
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package net.corda.core.crypto
|
|
||||||
|
|
||||||
import java.security.Provider
|
|
||||||
import java.security.SecureRandomSpi
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
class DelegatingSecureRandomService(provider: CordaSecurityProvider)
|
|
||||||
: Provider.Service(provider, "SecureRandom", "dummy-algorithm", UnsupportedSecureRandomSpi::javaClass.name, null, null) {
|
|
||||||
private val instance: SecureRandomSpi = UnsupportedSecureRandomSpi(algorithm)
|
|
||||||
override fun newInstance(param: Any?) = instance
|
|
||||||
|
|
||||||
private class UnsupportedSecureRandomSpi(private val algorithm: String) : SecureRandomSpi() {
|
|
||||||
override fun engineSetSeed(seed: ByteArray) = unsupported()
|
|
||||||
override fun engineNextBytes(bytes: ByteArray) = unsupported()
|
|
||||||
override fun engineGenerateSeed(numBytes: Int) = unsupported()
|
|
||||||
|
|
||||||
private fun unsupported(): Nothing = throw UnsupportedOperationException("$algorithm not supported")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,10 +0,0 @@
|
|||||||
package net.corda.core.crypto
|
|
||||||
|
|
||||||
import net.corda.core.crypto.internal.DigestAlgorithmFactory
|
|
||||||
import java.util.function.Supplier
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
private class DigestSupplier(private val algorithm: String) : Supplier<DigestAlgorithm> {
|
|
||||||
override fun get(): DigestAlgorithm = DigestAlgorithmFactory.create(algorithm)
|
|
||||||
val digestLength: Int by lazy { get().digestLength }
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
package net.corda.core.internal
|
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.utilities.contextLogger
|
|
||||||
import org.slf4j.Logger
|
|
||||||
import kotlin.reflect.KProperty
|
|
||||||
|
|
||||||
/** May go from null to non-null and vice-versa, and that's it. */
|
|
||||||
abstract class ToggleField<T>(val name: String) {
|
|
||||||
abstract fun get(): T?
|
|
||||||
fun set(value: T?) {
|
|
||||||
if (value != null) {
|
|
||||||
check(get() == null) { "$name already has a value." }
|
|
||||||
setImpl(value)
|
|
||||||
} else {
|
|
||||||
check(get() != null) { "$name is already null." }
|
|
||||||
clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract fun setImpl(value: T)
|
|
||||||
protected abstract fun clear()
|
|
||||||
operator fun getValue(thisRef: Any?, property: KProperty<*>) = get()
|
|
||||||
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) = set(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
@KeepForDJVM
|
|
||||||
class SimpleToggleField<T>(name: String, private val once: Boolean = false) : ToggleField<T>(name) {
|
|
||||||
private var holder: T? = null // Force T? in API for safety.
|
|
||||||
override fun get() = holder
|
|
||||||
override fun setImpl(value: T) { holder = value }
|
|
||||||
override fun clear() {
|
|
||||||
check(!once) { "Value of $name cannot be changed." }
|
|
||||||
holder = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@KeepForDJVM
|
|
||||||
class ThreadLocalToggleField<T>(name: String) : ToggleField<T>(name) {
|
|
||||||
private var holder: T? = null // Force T? in API for safety.
|
|
||||||
override fun get() = holder
|
|
||||||
override fun setImpl(value: T) { holder = value }
|
|
||||||
override fun clear() {
|
|
||||||
holder = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNUSED")
|
|
||||||
@KeepForDJVM
|
|
||||||
class InheritableThreadLocalToggleField<T>(name: String,
|
|
||||||
private val log: Logger = staticLog,
|
|
||||||
private val isAGlobalThreadBeingCreated: (Array<StackTraceElement>) -> Boolean) : ToggleField<T>(name) {
|
|
||||||
private companion object {
|
|
||||||
private val staticLog = contextLogger()
|
|
||||||
}
|
|
||||||
private var holder: T? = null // Force T? in API for safety.
|
|
||||||
override fun get() = holder
|
|
||||||
override fun setImpl(value: T) { holder = value }
|
|
||||||
override fun clear() {
|
|
||||||
holder = null
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
package net.corda.core.internal.rules
|
|
||||||
|
|
||||||
import net.corda.core.contracts.ContractState
|
|
||||||
|
|
||||||
// This file provides rules that depend on the targetVersion of the current Contract or Flow.
|
|
||||||
// In core, this is determined by means which are unavailable in the DJVM,
|
|
||||||
// so we must provide deterministic alternatives here.
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
object StateContractValidationEnforcementRule {
|
|
||||||
fun shouldEnforce(@Suppress("UNUSED_PARAMETER") state: ContractState): Boolean = true
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
package net.corda.core.internal.utilities
|
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
|
|
||||||
@KeepForDJVM
|
|
||||||
class PrivateInterner<T>(val verifier: IternabilityVerifier<T> = AlwaysInternableVerifier()) {
|
|
||||||
// DJVM implementation does not intern and does not use Guava
|
|
||||||
fun <S : T> intern(sample: S): S = sample
|
|
||||||
|
|
||||||
@KeepForDJVM
|
|
||||||
companion object {
|
|
||||||
@Suppress("UNUSED_PARAMETER")
|
|
||||||
fun findFor(clazz: Class<*>?): PrivateInterner<Any>? = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
|||||||
package net.corda.core.serialization
|
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.serialization.internal.effectiveSerializationEnv
|
|
||||||
import net.corda.core.utilities.ByteSequence
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An abstraction for serializing and deserializing objects, with support for versioning of the wire format via
|
|
||||||
* a header / prefix in the bytes.
|
|
||||||
*/
|
|
||||||
@KeepForDJVM
|
|
||||||
abstract class SerializationFactory {
|
|
||||||
/**
|
|
||||||
* Deserialize the bytes in to an object, using the prefixed bytes to determine the format.
|
|
||||||
*
|
|
||||||
* @param byteSequence The bytes to deserialize, including a format header prefix.
|
|
||||||
* @param clazz The class or superclass or the object to be deserialized, or [Any] or [Object] if unknown.
|
|
||||||
* @param context A context that configures various parameters to deserialization.
|
|
||||||
*/
|
|
||||||
abstract fun <T : Any> deserialize(byteSequence: ByteSequence, clazz: Class<T>, context: SerializationContext): T
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deserialize the bytes in to an object, using the prefixed bytes to determine the format.
|
|
||||||
*
|
|
||||||
* @param byteSequence The bytes to deserialize, including a format header prefix.
|
|
||||||
* @param clazz The class or superclass or the object to be deserialized, or [Any] or [Object] if unknown.
|
|
||||||
* @param context A context that configures various parameters to deserialization.
|
|
||||||
* @return deserialized object along with [SerializationContext] to identify encoding used.
|
|
||||||
*/
|
|
||||||
abstract fun <T : Any> deserializeWithCompatibleContext(byteSequence: ByteSequence, clazz: Class<T>, context: SerializationContext): ObjectWithCompatibleContext<T>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serialize an object to bytes using the preferred serialization format version from the context.
|
|
||||||
*
|
|
||||||
* @param obj The object to be serialized.
|
|
||||||
* @param context A context that configures various parameters to serialization, including the serialization format version.
|
|
||||||
*/
|
|
||||||
abstract fun <T : Any> serialize(obj: T, context: SerializationContext): SerializedBytes<T>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If there is a need to nest serialization/deserialization with a modified context during serialization or deserialization,
|
|
||||||
* this will return the current context used to start serialization/deserialization.
|
|
||||||
*/
|
|
||||||
val currentContext: SerializationContext? get() = _currentContext
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A context to use as a default if you do not require a specially configured context. It will be the current context
|
|
||||||
* if the use is somehow nested (see [currentContext]).
|
|
||||||
*/
|
|
||||||
val defaultContext: SerializationContext get() = currentContext ?: effectiveSerializationEnv.p2pContext
|
|
||||||
|
|
||||||
private var _currentContext: SerializationContext? = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change the current context inside the block to that supplied.
|
|
||||||
*/
|
|
||||||
fun <T> withCurrentContext(context: SerializationContext?, block: () -> T): T {
|
|
||||||
return if (context == null) {
|
|
||||||
block()
|
|
||||||
} else {
|
|
||||||
val priorContext = _currentContext
|
|
||||||
_currentContext = context
|
|
||||||
try {
|
|
||||||
block()
|
|
||||||
} finally {
|
|
||||||
_currentContext = priorContext
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allow subclasses to temporarily mark themselves as the current factory for the current thread during serialization/deserialization.
|
|
||||||
* Will restore the prior context on exiting the block.
|
|
||||||
*/
|
|
||||||
fun <T> asCurrent(block: SerializationFactory.() -> T): T {
|
|
||||||
val priorContext = _currentFactory
|
|
||||||
_currentFactory= this
|
|
||||||
try {
|
|
||||||
return this.block()
|
|
||||||
} finally {
|
|
||||||
_currentFactory = priorContext
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private var _currentFactory: SerializationFactory? = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A default factory for serialization/deserialization, taking into account the [currentFactory] if set.
|
|
||||||
*/
|
|
||||||
val defaultFactory: SerializationFactory get() = currentFactory ?: effectiveSerializationEnv.serializationFactory
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If there is a need to nest serialization/deserialization with a modified context during serialization or deserialization,
|
|
||||||
* this will return the current factory used to start serialization/deserialization.
|
|
||||||
*/
|
|
||||||
val currentFactory: SerializationFactory? get() = _currentFactory
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
package net.corda.core.serialization.internal
|
|
||||||
|
|
||||||
import net.corda.core.contracts.Attachment
|
|
||||||
import java.net.URL
|
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
private class AttachmentsHolderImpl : AttachmentsHolder {
|
|
||||||
private val attachments = LinkedHashMap<URL, Pair<URL, Attachment>>()
|
|
||||||
|
|
||||||
override val size: Int get() = attachments.size
|
|
||||||
|
|
||||||
override fun getKey(key: URL): URL? {
|
|
||||||
return attachments[key]?.first
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun get(key: URL): Attachment? {
|
|
||||||
return attachments[key]?.second
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun set(key: URL, value: Attachment) {
|
|
||||||
attachments[key] = key to value
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'org.jetbrains.kotlin.jvm'
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
testImplementation project(path: ':core-deterministic', configuration: 'deterministicArtifacts')
|
|
||||||
testImplementation project(path: ':serialization-deterministic', configuration: 'deterministicArtifacts')
|
|
||||||
testImplementation project(path: ':core-deterministic:testing:verifier', configuration: 'deterministicArtifacts')
|
|
||||||
testImplementation project(path: ':core-deterministic:testing:data', configuration: 'testData')
|
|
||||||
testImplementation(project(':finance:contracts')) {
|
|
||||||
transitive = false
|
|
||||||
}
|
|
||||||
testImplementation(project(':finance:workflows')) {
|
|
||||||
transitive = false
|
|
||||||
}
|
|
||||||
|
|
||||||
testImplementation "org.slf4j:slf4j-api:$slf4j_version"
|
|
||||||
testRuntimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version"
|
|
||||||
testImplementation "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
|
||||||
testImplementation "org.assertj:assertj-core:$assertj_version"
|
|
||||||
testImplementation "junit:junit:$junit_version"
|
|
||||||
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:${junit_vintage_version}"
|
|
||||||
testRuntimeOnly "org.junit.platform:junit-platform-launcher:${junit_platform_version}"
|
|
||||||
}
|
|
||||||
|
|
||||||
// This module has no artifact and only contains tests.
|
|
||||||
tasks.named('jar', Jar) {
|
|
||||||
enabled = false
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'org.jetbrains.kotlin.jvm'
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations {
|
|
||||||
testData {
|
|
||||||
canBeResolved = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
testImplementation project(':core')
|
|
||||||
testImplementation project(':finance:workflows')
|
|
||||||
testImplementation project(':node-driver')
|
|
||||||
testImplementation project(path: ':core-deterministic:testing:verifier', configuration: 'runtimeArtifacts')
|
|
||||||
|
|
||||||
testImplementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
|
|
||||||
testImplementation "org.jetbrains.kotlin:kotlin-reflect"
|
|
||||||
|
|
||||||
testImplementation "junit:junit:$junit_version"
|
|
||||||
|
|
||||||
testRuntimeOnly "org.junit.vintage:junit-vintage-engine:${junit_vintage_version}"
|
|
||||||
testRuntimeOnly "org.junit.platform:junit-platform-launcher:${junit_platform_version}"
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.named('jar', Jar) {
|
|
||||||
enabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
def test = tasks.named('test', Test) {
|
|
||||||
filter {
|
|
||||||
// Running this class is the whole point, so include it explicitly.
|
|
||||||
includeTestsMatching "net.corda.deterministic.data.GenerateData"
|
|
||||||
}
|
|
||||||
// force execution of these tests to generate artifacts required by other module (eg. VerifyTransactionTest)
|
|
||||||
// note: required by Gradle Build Cache.
|
|
||||||
outputs.upToDateWhen { false }
|
|
||||||
}
|
|
||||||
|
|
||||||
def testDataJar = file("$buildDir/test-data.jar")
|
|
||||||
artifacts {
|
|
||||||
archives file: testDataJar, type: 'jar', builtBy: test
|
|
||||||
testData file: testDataJar, type: 'jar', builtBy: test
|
|
||||||
}
|
|
@ -1,92 +0,0 @@
|
|||||||
package net.corda.deterministic.data
|
|
||||||
|
|
||||||
import net.corda.core.serialization.deserialize
|
|
||||||
import net.corda.deterministic.verifier.LocalSerializationRule
|
|
||||||
import net.corda.deterministic.verifier.TransactionVerificationRequest
|
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.Rule
|
|
||||||
import org.junit.Test
|
|
||||||
import java.io.FileNotFoundException
|
|
||||||
import java.net.URLClassLoader
|
|
||||||
import java.nio.file.Files
|
|
||||||
import java.nio.file.Path
|
|
||||||
import java.nio.file.Paths
|
|
||||||
import java.nio.file.attribute.FileTime
|
|
||||||
import java.util.*
|
|
||||||
import java.util.Calendar.*
|
|
||||||
import java.util.jar.JarOutputStream
|
|
||||||
import java.util.zip.Deflater.NO_COMPRESSION
|
|
||||||
import java.util.zip.ZipEntry
|
|
||||||
import java.util.zip.ZipEntry.*
|
|
||||||
import kotlin.reflect.jvm.jvmName
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Use the JUnit framework to generate a JAR of test data.
|
|
||||||
*/
|
|
||||||
class GenerateData {
|
|
||||||
companion object {
|
|
||||||
private val CONSTANT_TIME: FileTime = FileTime.fromMillis(
|
|
||||||
GregorianCalendar(1980, FEBRUARY, 1).apply { timeZone = TimeZone.getTimeZone("UTC") }.timeInMillis
|
|
||||||
)
|
|
||||||
private const val KEYSTORE_ALIAS = "tx"
|
|
||||||
private val KEYSTORE_PASSWORD = "deterministic".toCharArray()
|
|
||||||
private val TEST_DATA: Path = Paths.get("build", "test-data.jar")
|
|
||||||
|
|
||||||
private fun compressed(name: String) = ZipEntry(name).apply {
|
|
||||||
lastModifiedTime = CONSTANT_TIME
|
|
||||||
method = DEFLATED
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun directory(name: String) = ZipEntry(name).apply {
|
|
||||||
lastModifiedTime = CONSTANT_TIME
|
|
||||||
method = STORED
|
|
||||||
compressedSize = 0
|
|
||||||
size = 0
|
|
||||||
crc = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Rule
|
|
||||||
@JvmField
|
|
||||||
val testSerialization = LocalSerializationRule(GenerateData::class.jvmName)
|
|
||||||
|
|
||||||
@Before
|
|
||||||
fun createTransactions() {
|
|
||||||
JarOutputStream(Files.newOutputStream(TEST_DATA)).use { jar ->
|
|
||||||
jar.setComment("Test data for Deterministic Corda")
|
|
||||||
jar.setLevel(NO_COMPRESSION)
|
|
||||||
|
|
||||||
// Serialised transactions for the Enclavelet
|
|
||||||
jar.putNextEntry(directory("txverify"))
|
|
||||||
jar.putNextEntry(compressed("txverify/tx-success.bin"))
|
|
||||||
TransactionGenerator.writeSuccess(jar)
|
|
||||||
jar.putNextEntry(compressed("txverify/tx-failure.bin"))
|
|
||||||
TransactionGenerator.writeFailure(jar)
|
|
||||||
|
|
||||||
// KeyStore containing an EC private key.
|
|
||||||
jar.putNextEntry(directory("keystore"))
|
|
||||||
jar.putNextEntry(compressed("keystore/txsignature.pfx"))
|
|
||||||
KeyStoreGenerator.writeKeyStore(jar, KEYSTORE_ALIAS, KEYSTORE_PASSWORD)
|
|
||||||
}
|
|
||||||
testSerialization.reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout = 300_000)
|
|
||||||
fun verifyTransactions() {
|
|
||||||
URLClassLoader(arrayOf(TEST_DATA.toUri().toURL())).use { cl ->
|
|
||||||
cl.loadResource("txverify/tx-success.bin")
|
|
||||||
.deserialize<TransactionVerificationRequest>()
|
|
||||||
.toLedgerTransaction()
|
|
||||||
.verify()
|
|
||||||
|
|
||||||
cl.loadResource("txverify/tx-failure.bin")
|
|
||||||
.deserialize<TransactionVerificationRequest>()
|
|
||||||
.toLedgerTransaction()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ClassLoader.loadResource(resourceName: String): ByteArray {
|
|
||||||
return getResourceAsStream(resourceName)?.use { it.readBytes() }
|
|
||||||
?: throw FileNotFoundException(resourceName)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
package net.corda.deterministic.data
|
|
||||||
|
|
||||||
import org.bouncycastle.asn1.x500.X500Name
|
|
||||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
|
|
||||||
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder
|
|
||||||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder
|
|
||||||
import java.io.OutputStream
|
|
||||||
import java.math.BigInteger.TEN
|
|
||||||
import java.security.KeyPairGenerator
|
|
||||||
import java.security.KeyStore
|
|
||||||
import java.security.spec.ECGenParameterSpec
|
|
||||||
import java.util.*
|
|
||||||
import java.util.Calendar.*
|
|
||||||
|
|
||||||
object KeyStoreGenerator {
|
|
||||||
private val keyPairGenerator: KeyPairGenerator = KeyPairGenerator.getInstance("EC").apply {
|
|
||||||
initialize(ECGenParameterSpec("secp256k1"))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun writeKeyStore(output: OutputStream, alias: String, password: CharArray) {
|
|
||||||
val keyPair = keyPairGenerator.generateKeyPair()
|
|
||||||
val signer = JcaContentSignerBuilder("SHA256WithECDSA").build(keyPair.private)
|
|
||||||
val dname = X500Name("CN=Enclavelet")
|
|
||||||
val startDate = Calendar.getInstance().let { cal ->
|
|
||||||
cal.time = Date()
|
|
||||||
cal.add(HOUR, -1)
|
|
||||||
cal.time
|
|
||||||
}
|
|
||||||
val endDate = Calendar.getInstance().let { cal ->
|
|
||||||
cal.time = startDate
|
|
||||||
cal.add(YEAR, 1)
|
|
||||||
cal.time
|
|
||||||
}
|
|
||||||
val certificate = JcaX509v3CertificateBuilder(
|
|
||||||
dname,
|
|
||||||
TEN,
|
|
||||||
startDate,
|
|
||||||
endDate,
|
|
||||||
dname,
|
|
||||||
keyPair.public
|
|
||||||
).build(signer)
|
|
||||||
val x509 = JcaX509CertificateConverter().getCertificate(certificate)
|
|
||||||
|
|
||||||
KeyStore.getInstance("PKCS12").apply {
|
|
||||||
load(null, password)
|
|
||||||
setKeyEntry(alias, keyPair.private, password, arrayOf(x509))
|
|
||||||
store(output, password)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,115 +0,0 @@
|
|||||||
package net.corda.deterministic.data
|
|
||||||
|
|
||||||
import com.nhaarman.mockito_kotlin.doReturn
|
|
||||||
import com.nhaarman.mockito_kotlin.mock
|
|
||||||
import com.nhaarman.mockito_kotlin.whenever
|
|
||||||
import net.corda.core.crypto.entropyToKeyPair
|
|
||||||
import net.corda.core.identity.AnonymousParty
|
|
||||||
import net.corda.core.identity.CordaX500Name
|
|
||||||
import net.corda.core.identity.Party
|
|
||||||
import net.corda.core.node.services.IdentityService
|
|
||||||
import net.corda.core.serialization.serialize
|
|
||||||
import net.corda.deterministic.verifier.MockContractAttachment
|
|
||||||
import net.corda.deterministic.verifier.SampleCommandData
|
|
||||||
import net.corda.deterministic.verifier.TransactionVerificationRequest
|
|
||||||
import net.corda.finance.POUNDS
|
|
||||||
import net.corda.finance.`issued by`
|
|
||||||
import net.corda.finance.contracts.asset.Cash.Commands.Issue
|
|
||||||
import net.corda.finance.contracts.asset.Cash.Commands.Move
|
|
||||||
import net.corda.finance.contracts.asset.Cash.Companion.PROGRAM_ID
|
|
||||||
import net.corda.finance.contracts.asset.Cash.State
|
|
||||||
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
|
||||||
import net.corda.testing.core.TestIdentity
|
|
||||||
import net.corda.testing.core.getTestPartyAndCertificate
|
|
||||||
import net.corda.testing.node.MockServices
|
|
||||||
import net.corda.testing.node.ledger
|
|
||||||
import java.io.OutputStream
|
|
||||||
import java.math.BigInteger
|
|
||||||
import java.security.KeyPair
|
|
||||||
import java.security.PublicKey
|
|
||||||
|
|
||||||
object TransactionGenerator {
|
|
||||||
private val DUMMY_NOTARY: Party = TestIdentity(DUMMY_NOTARY_NAME, 20).party
|
|
||||||
|
|
||||||
private val DUMMY_CASH_ISSUER_KEY: KeyPair = entropyToKeyPair(BigInteger.valueOf(10))
|
|
||||||
private val DUMMY_CASH_ISSUER_IDENTITY = getTestPartyAndCertificate(Party(CordaX500Name("Snake Oil Issuer", "London", "GB"), DUMMY_CASH_ISSUER_KEY.public))
|
|
||||||
private val DUMMY_CASH_ISSUER = DUMMY_CASH_ISSUER_IDENTITY.party.ref(1)
|
|
||||||
|
|
||||||
private val megaCorp = TestIdentity(CordaX500Name("MegaCorp", "London", "GB"))
|
|
||||||
private val MEGA_CORP: Party = megaCorp.party
|
|
||||||
private val MEGA_CORP_PUBKEY: PublicKey = megaCorp.keyPair.public
|
|
||||||
private val MINI_CORP_PUBKEY: PublicKey = TestIdentity(CordaX500Name("MiniCorp", "London", "GB")).keyPair.public
|
|
||||||
|
|
||||||
private val ledgerServices = MockServices(emptyList(), MEGA_CORP.name, mock<IdentityService>().also {
|
|
||||||
doReturn(MEGA_CORP).whenever(it).partyFromKey(MEGA_CORP_PUBKEY)
|
|
||||||
doReturn(DUMMY_CASH_ISSUER.party).whenever(it).partyFromKey(DUMMY_CASH_ISSUER_KEY.public)
|
|
||||||
})
|
|
||||||
|
|
||||||
fun writeSuccess(output: OutputStream) {
|
|
||||||
ledgerServices.ledger(DUMMY_NOTARY) {
|
|
||||||
// Issue a couple of cash states and spend them.
|
|
||||||
val wtx1 = transaction {
|
|
||||||
attachments(PROGRAM_ID)
|
|
||||||
output(PROGRAM_ID, "c1", State(1000.POUNDS `issued by` DUMMY_CASH_ISSUER, AnonymousParty(MEGA_CORP_PUBKEY)))
|
|
||||||
command(DUMMY_CASH_ISSUER.party.owningKey, Issue())
|
|
||||||
verifies()
|
|
||||||
}
|
|
||||||
val wtx2 = transaction {
|
|
||||||
attachments(PROGRAM_ID)
|
|
||||||
output(PROGRAM_ID, "c2", State(2000.POUNDS `issued by` DUMMY_CASH_ISSUER, AnonymousParty(MEGA_CORP_PUBKEY)))
|
|
||||||
command(DUMMY_CASH_ISSUER.party.owningKey, Issue())
|
|
||||||
verifies()
|
|
||||||
}
|
|
||||||
val wtx3 = transaction {
|
|
||||||
attachments(PROGRAM_ID)
|
|
||||||
input("c1")
|
|
||||||
input("c2")
|
|
||||||
output(PROGRAM_ID, "c3", State(3000.POUNDS `issued by` DUMMY_CASH_ISSUER, AnonymousParty(MINI_CORP_PUBKEY)))
|
|
||||||
command(MEGA_CORP_PUBKEY, Move())
|
|
||||||
verifies()
|
|
||||||
}
|
|
||||||
val contractAttachment = MockContractAttachment(interpreter.services.cordappProvider.getContractAttachmentID(PROGRAM_ID)!!, PROGRAM_ID)
|
|
||||||
TransactionVerificationRequest(
|
|
||||||
wtx3.serialize(),
|
|
||||||
arrayOf(wtx1.serialize(), wtx2.serialize()),
|
|
||||||
arrayOf(contractAttachment.serialize().bytes),
|
|
||||||
ledgerServices.networkParameters.serialize())
|
|
||||||
.serialize()
|
|
||||||
.writeTo(output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun writeFailure(output: OutputStream) {
|
|
||||||
ledgerServices.ledger(DUMMY_NOTARY) {
|
|
||||||
// Issue a couple of cash states and spend them.
|
|
||||||
val wtx1 = transaction {
|
|
||||||
attachments(PROGRAM_ID)
|
|
||||||
output(PROGRAM_ID, "c1", State(1000.POUNDS `issued by` DUMMY_CASH_ISSUER, AnonymousParty(MEGA_CORP_PUBKEY)))
|
|
||||||
command(DUMMY_CASH_ISSUER.party.owningKey, Issue())
|
|
||||||
verifies()
|
|
||||||
}
|
|
||||||
val wtx2 = transaction {
|
|
||||||
attachments(PROGRAM_ID)
|
|
||||||
output(PROGRAM_ID, "c2", State(2000.POUNDS `issued by` DUMMY_CASH_ISSUER, AnonymousParty(MEGA_CORP_PUBKEY)))
|
|
||||||
command(DUMMY_CASH_ISSUER.party.owningKey, Issue())
|
|
||||||
verifies()
|
|
||||||
}
|
|
||||||
val wtx3 = transaction {
|
|
||||||
attachments(PROGRAM_ID)
|
|
||||||
input("c1")
|
|
||||||
input("c2")
|
|
||||||
command(DUMMY_CASH_ISSUER.party.owningKey, SampleCommandData)
|
|
||||||
output(PROGRAM_ID, "c3", State(3000.POUNDS `issued by` DUMMY_CASH_ISSUER, AnonymousParty(MINI_CORP_PUBKEY)))
|
|
||||||
failsWith("Required ${Move::class.java.canonicalName} command")
|
|
||||||
}
|
|
||||||
val contractAttachment = MockContractAttachment(interpreter.services.cordappProvider.getContractAttachmentID(PROGRAM_ID)!!, PROGRAM_ID)
|
|
||||||
TransactionVerificationRequest(
|
|
||||||
wtx3.serialize(),
|
|
||||||
arrayOf(wtx1.serialize(), wtx2.serialize()),
|
|
||||||
arrayOf(contractAttachment.serialize().bytes),
|
|
||||||
ledgerServices.networkParameters.serialize())
|
|
||||||
.serialize()
|
|
||||||
.writeTo(output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
package net.corda.deterministic;
|
|
||||||
|
|
||||||
import java.security.Provider;
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.security.SecureRandomSpi;
|
|
||||||
import java.security.Security;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Temporarily restore Sun's [SecureRandom] provider.
|
|
||||||
* This is ONLY for allowing us to generate test data, e.g. signatures.
|
|
||||||
*
|
|
||||||
* JDK11 upgrade: rewritten in Java to gain access to private internal JDK classes via module directives (not available to Kotlin compiler):
|
|
||||||
* sun.security.provider.SecureRandom()
|
|
||||||
*/
|
|
||||||
public class CheatingSecurityProvider extends Provider implements AutoCloseable {
|
|
||||||
|
|
||||||
private static AtomicInteger counter = new AtomicInteger();
|
|
||||||
|
|
||||||
@SuppressWarnings("deprecation") // JDK11: should replace with Provider(String name, double version, String info) (since 9)
|
|
||||||
public CheatingSecurityProvider() {
|
|
||||||
super("Cheat-" + counter.getAndIncrement(), 1.8, "Cheat security provider");
|
|
||||||
putService(new CheatingSecureRandomService(this));
|
|
||||||
assertEquals(1, Security.insertProviderAt(this, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() {
|
|
||||||
Security.removeProvider(getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
private class SunSecureRandom extends SecureRandom {
|
|
||||||
public SunSecureRandom() {
|
|
||||||
// JDK11 upgrade: rewritten in Java to gain access to private internal JDK classes via open module directive
|
|
||||||
super(new sun.security.provider.SecureRandom(), null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CheatingSecureRandomService extends Provider.Service {
|
|
||||||
|
|
||||||
public CheatingSecureRandomService(Provider provider) {
|
|
||||||
super(provider, "SecureRandom", "CheatingPRNG", CheatingSecureRandomSpi.class.getName(), null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private SecureRandomSpi instance = new CheatingSecureRandomSpi();
|
|
||||||
|
|
||||||
public Object newInstance(Object constructorParameter){
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class CheatingSecureRandomSpi extends SecureRandomSpi {
|
|
||||||
|
|
||||||
private SecureRandom secureRandom = new SunSecureRandom();
|
|
||||||
|
|
||||||
public void engineSetSeed(byte[] seed) { secureRandom.setSeed(seed); }
|
|
||||||
public void engineNextBytes(byte[] bytes) { secureRandom.nextBytes(bytes); }
|
|
||||||
public byte[] engineGenerateSeed(int numBytes) { return secureRandom.generateSeed(numBytes); }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
package net.corda.core.internal
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stubbing out non-deterministic method.
|
|
||||||
*/
|
|
||||||
fun <T: Any> createInstancesOfClassesImplementing(@Suppress("UNUSED_PARAMETER") classloader: ClassLoader, @Suppress("UNUSED_PARAMETER") clazz: Class<T>,
|
|
||||||
@Suppress("UNUSED_PARAMETER") classVersionRange: IntRange? = null): Set<T> {
|
|
||||||
return emptySet()
|
|
||||||
}
|
|
@ -1,70 +0,0 @@
|
|||||||
package net.corda.deterministic
|
|
||||||
|
|
||||||
import net.corda.core.CordaException
|
|
||||||
import net.corda.core.contracts.AttachmentResolutionException
|
|
||||||
import net.corda.core.contracts.TransactionResolutionException
|
|
||||||
import net.corda.core.contracts.TransactionVerificationException.*
|
|
||||||
import net.corda.core.crypto.SecureHash
|
|
||||||
import net.corda.core.identity.CordaX500Name
|
|
||||||
import net.corda.core.identity.Party
|
|
||||||
import org.junit.Assert.*
|
|
||||||
import org.junit.Test
|
|
||||||
import java.security.PublicKey
|
|
||||||
import kotlin.test.assertFailsWith
|
|
||||||
|
|
||||||
class CordaExceptionTest {
|
|
||||||
companion object {
|
|
||||||
const val CONTRACT_CLASS = "com.r3.corda.contracts.TestContract"
|
|
||||||
val TEST_HASH = SecureHash.zeroHash
|
|
||||||
val TX_ID = SecureHash.allOnesHash
|
|
||||||
|
|
||||||
val ALICE_NAME = CordaX500Name("Alice Corp", "Madrid", "ES")
|
|
||||||
val ALICE_KEY: PublicKey = object : PublicKey {
|
|
||||||
override fun getAlgorithm(): String = "TEST-256"
|
|
||||||
override fun getFormat(): String = "<none>"
|
|
||||||
override fun getEncoded() = byteArrayOf()
|
|
||||||
}
|
|
||||||
val ALICE = Party(ALICE_NAME, ALICE_KEY)
|
|
||||||
|
|
||||||
val BOB_NAME = CordaX500Name("Bob Plc", "Rome", "IT")
|
|
||||||
val BOB_KEY: PublicKey = object : PublicKey {
|
|
||||||
override fun getAlgorithm(): String = "TEST-512"
|
|
||||||
override fun getFormat(): String = "<none>"
|
|
||||||
override fun getEncoded() = byteArrayOf()
|
|
||||||
}
|
|
||||||
val BOB = Party(BOB_NAME, BOB_KEY)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testCordaException() {
|
|
||||||
val ex = assertFailsWith<CordaException> { throw CordaException("BAD THING") }
|
|
||||||
assertEquals("BAD THING", ex.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testAttachmentResolutionException() {
|
|
||||||
val ex = assertFailsWith<AttachmentResolutionException> { throw AttachmentResolutionException(TEST_HASH) }
|
|
||||||
assertEquals(TEST_HASH, ex.hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testTransactionResolutionException() {
|
|
||||||
val ex = assertFailsWith<TransactionResolutionException> { throw TransactionResolutionException(TEST_HASH) }
|
|
||||||
assertEquals(TEST_HASH, ex.hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testConflictingAttachmentsRejection() {
|
|
||||||
val ex = assertFailsWith<ConflictingAttachmentsRejection> { throw ConflictingAttachmentsRejection(TX_ID, CONTRACT_CLASS) }
|
|
||||||
assertEquals(TX_ID, ex.txId)
|
|
||||||
assertEquals(CONTRACT_CLASS, ex.contractClass)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testNotaryChangeInWrongTransactionType() {
|
|
||||||
val ex = assertFailsWith<NotaryChangeInWrongTransactionType> { throw NotaryChangeInWrongTransactionType(TX_ID, ALICE, BOB) }
|
|
||||||
assertEquals(TX_ID, ex.txId)
|
|
||||||
assertEquals(ALICE, ex.txNotary)
|
|
||||||
assertEquals(BOB, ex.outputNotary)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
package net.corda.deterministic
|
|
||||||
|
|
||||||
import org.junit.AssumptionViolatedException
|
|
||||||
import org.junit.rules.TestRule
|
|
||||||
import org.junit.runner.Description
|
|
||||||
import org.junit.runners.model.Statement
|
|
||||||
import java.security.KeyPair
|
|
||||||
import java.security.KeyStore
|
|
||||||
import java.security.PrivateKey
|
|
||||||
import java.security.cert.TrustAnchor
|
|
||||||
import java.security.cert.X509Certificate
|
|
||||||
|
|
||||||
class KeyStoreProvider(private val storeName: String, private val storePassword: String) : TestRule {
|
|
||||||
private lateinit var keyStore: KeyStore
|
|
||||||
|
|
||||||
private fun loadKeyStoreResource(resourceName: String, password: CharArray, type: String = "PKCS12"): KeyStore {
|
|
||||||
return KeyStore.getInstance(type).apply {
|
|
||||||
// Skip these tests if we cannot load the keystore.
|
|
||||||
val keyStream = KeyStoreProvider::class.java.classLoader.getResourceAsStream(resourceName)
|
|
||||||
?: throw AssumptionViolatedException("KeyStore $resourceName not found")
|
|
||||||
keyStream.use { input ->
|
|
||||||
load(input, password)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun apply(statement: Statement, description: Description?): Statement {
|
|
||||||
return object : Statement() {
|
|
||||||
override fun evaluate() {
|
|
||||||
keyStore = loadKeyStoreResource(storeName, storePassword.toCharArray())
|
|
||||||
statement.evaluate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getKeyPair(alias: String): KeyPair {
|
|
||||||
val privateKey = keyStore.getKey(alias, storePassword.toCharArray()) as PrivateKey
|
|
||||||
return KeyPair(keyStore.getCertificate(alias).publicKey, privateKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNUSED")
|
|
||||||
fun trustAnchorsFor(vararg aliases: String): Set<TrustAnchor>
|
|
||||||
= aliases.map { alias -> TrustAnchor(keyStore.getCertificate(alias) as X509Certificate, null) }.toSet()
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
package net.corda.deterministic
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream
|
|
||||||
import java.io.IOException
|
|
||||||
|
|
||||||
private val classLoader: ClassLoader = object {}.javaClass.classLoader
|
|
||||||
|
|
||||||
@Throws(IOException::class)
|
|
||||||
fun bytesOfResource(resourceName: String): ByteArray {
|
|
||||||
return ByteArrayOutputStream().let { baos ->
|
|
||||||
classLoader.getResourceAsStream(resourceName).copyTo(baos)
|
|
||||||
baos.toByteArray()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,79 +0,0 @@
|
|||||||
package net.corda.deterministic.contracts
|
|
||||||
|
|
||||||
import net.corda.core.contracts.Attachment
|
|
||||||
import net.corda.core.crypto.SecureHash
|
|
||||||
import net.corda.core.identity.CordaX500Name
|
|
||||||
import net.corda.core.identity.Party
|
|
||||||
import org.junit.Assert.*
|
|
||||||
import org.junit.Before
|
|
||||||
import org.junit.Test
|
|
||||||
import java.io.ByteArrayOutputStream
|
|
||||||
import java.io.InputStream
|
|
||||||
import java.security.PublicKey
|
|
||||||
import java.util.jar.JarOutputStream
|
|
||||||
import java.util.zip.Deflater.*
|
|
||||||
import java.util.zip.ZipEntry
|
|
||||||
|
|
||||||
class AttachmentTest {
|
|
||||||
private companion object {
|
|
||||||
private val data = byteArrayOf(0x73, 0x71, 0x18, 0x5F, 0x3A, 0x47, -0x22, 0x38)
|
|
||||||
private val jarData: ByteArray = ByteArrayOutputStream().let { baos ->
|
|
||||||
JarOutputStream(baos).use { jar ->
|
|
||||||
jar.setLevel(BEST_COMPRESSION)
|
|
||||||
jar.putNextEntry(ZipEntry("data.bin").apply { method = DEFLATED })
|
|
||||||
data.inputStream().copyTo(jar)
|
|
||||||
}
|
|
||||||
baos.toByteArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
private val ALICE_NAME = CordaX500Name("Alice Corp", "Madrid", "ES")
|
|
||||||
private val ALICE_KEY: PublicKey = object : PublicKey {
|
|
||||||
override fun getAlgorithm(): String = "TEST-256"
|
|
||||||
override fun getFormat(): String = "<none>"
|
|
||||||
override fun getEncoded() = byteArrayOf()
|
|
||||||
}
|
|
||||||
private val ALICE = Party(ALICE_NAME, ALICE_KEY)
|
|
||||||
}
|
|
||||||
|
|
||||||
private lateinit var attachment: Attachment
|
|
||||||
|
|
||||||
@Before
|
|
||||||
fun setup() {
|
|
||||||
attachment = object : Attachment {
|
|
||||||
override val signerKeys: List<PublicKey>
|
|
||||||
get() = listOf(ALICE_KEY)
|
|
||||||
override val id: SecureHash
|
|
||||||
get() = SecureHash.allOnesHash
|
|
||||||
override val signers: List<Party>
|
|
||||||
get() = listOf(ALICE)
|
|
||||||
override val size: Int
|
|
||||||
get() = jarData.size
|
|
||||||
|
|
||||||
override fun open(): InputStream {
|
|
||||||
return jarData.inputStream()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testAttachmentJar() {
|
|
||||||
attachment.openAsJAR().use { jar ->
|
|
||||||
val entry = jar.nextJarEntry ?: return@use
|
|
||||||
assertEquals("data.bin", entry.name)
|
|
||||||
val entryData = ByteArrayOutputStream().use {
|
|
||||||
jar.copyTo(it)
|
|
||||||
it.toByteArray()
|
|
||||||
}
|
|
||||||
assertArrayEquals(data, entryData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testExtractFromAttachment() {
|
|
||||||
val resultData = ByteArrayOutputStream().use {
|
|
||||||
attachment.extractFile("data.bin", it)
|
|
||||||
it.toByteArray()
|
|
||||||
}
|
|
||||||
assertArrayEquals(data, resultData)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
package net.corda.deterministic.contracts
|
|
||||||
|
|
||||||
import net.corda.core.contracts.PrivacySalt
|
|
||||||
import org.junit.Test
|
|
||||||
import kotlin.test.*
|
|
||||||
|
|
||||||
class PrivacySaltTest {
|
|
||||||
private companion object {
|
|
||||||
private const val SALT_SIZE = 32
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testValidSalt() {
|
|
||||||
PrivacySalt(ByteArray(SALT_SIZE) { 0x14 })
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testInvalidSaltWithAllZeros() {
|
|
||||||
val ex = assertFailsWith<IllegalArgumentException> { PrivacySalt(ByteArray(SALT_SIZE)) }
|
|
||||||
assertEquals("Privacy salt should not be all zeros.", ex.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testTooShortPrivacySaltForSHA256() {
|
|
||||||
val ex = assertFailsWith<IllegalArgumentException> { PrivacySalt(ByteArray(SALT_SIZE - 1) { 0x7f }) }
|
|
||||||
assertEquals("Privacy salt should be at least 32 bytes.", ex.message)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
package net.corda.deterministic.contracts
|
|
||||||
|
|
||||||
import net.corda.core.contracts.UniqueIdentifier
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
|
||||||
import org.junit.Assert.*
|
|
||||||
import org.junit.Test
|
|
||||||
import java.util.*
|
|
||||||
import kotlin.reflect.full.primaryConstructor
|
|
||||||
import kotlin.test.assertFailsWith
|
|
||||||
|
|
||||||
class UniqueIdentifierTest {
|
|
||||||
private companion object {
|
|
||||||
private const val NAME = "MyName"
|
|
||||||
private val TEST_UUID: UUID = UUID.fromString("00000000-1111-2222-3333-444444444444")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testNewInstance() {
|
|
||||||
val id = UniqueIdentifier(NAME, TEST_UUID)
|
|
||||||
assertEquals("${NAME}_$TEST_UUID", id.toString())
|
|
||||||
assertEquals(NAME, id.externalId)
|
|
||||||
assertEquals(TEST_UUID, id.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testPrimaryConstructor() {
|
|
||||||
val primary = UniqueIdentifier::class.primaryConstructor ?: throw AssertionError("primary constructor missing")
|
|
||||||
assertThat(primary.call(NAME, TEST_UUID)).isEqualTo(UniqueIdentifier(NAME, TEST_UUID))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testConstructors() {
|
|
||||||
assertEquals(1, UniqueIdentifier::class.constructors.size)
|
|
||||||
val ex = assertFailsWith<IllegalArgumentException> { UniqueIdentifier::class.constructors.first().call() }
|
|
||||||
assertThat(ex).hasMessage("Callable expects 2 arguments, but 0 were provided.")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,68 +0,0 @@
|
|||||||
@file:JvmName("CryptoSignUtils")
|
|
||||||
|
|
||||||
package net.corda.deterministic.crypto
|
|
||||||
|
|
||||||
import net.corda.core.crypto.*
|
|
||||||
import net.corda.core.crypto.Crypto.findSignatureScheme
|
|
||||||
import net.corda.core.crypto.Crypto.isSupportedSignatureScheme
|
|
||||||
import net.corda.core.serialization.serialize
|
|
||||||
import java.security.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a slightly modified copy of signing utils from net.corda.core.crypto.Crypto, which are normally removed from DJVM.
|
|
||||||
* However, we need those for TransactionSignatureTest.
|
|
||||||
*/
|
|
||||||
object CryptoSignUtils {
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(InvalidKeyException::class, SignatureException::class)
|
|
||||||
fun doSign(schemeCodeName: String, privateKey: PrivateKey, clearData: ByteArray): ByteArray {
|
|
||||||
return doSign(findSignatureScheme(schemeCodeName), privateKey, clearData)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic way to sign [ByteArray] data with a [PrivateKey] and a known [Signature].
|
|
||||||
* @param signatureScheme a [SignatureScheme] object, retrieved from supported signature schemes, see [Crypto].
|
|
||||||
* @param privateKey the signer's [PrivateKey].
|
|
||||||
* @param clearData the data/message to be signed in [ByteArray] form (usually the Merkle root).
|
|
||||||
* @return the digital signature (in [ByteArray]) on the input message.
|
|
||||||
* @throws IllegalArgumentException if the signature scheme is not supported for this private key.
|
|
||||||
* @throws InvalidKeyException if the private key is invalid.
|
|
||||||
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(InvalidKeyException::class, SignatureException::class)
|
|
||||||
fun doSign(signatureScheme: SignatureScheme, privateKey: PrivateKey, clearData: ByteArray): ByteArray {
|
|
||||||
require(isSupportedSignatureScheme(signatureScheme)) {
|
|
||||||
"Unsupported key/algorithm for schemeCodeName: ${signatureScheme.schemeCodeName}"
|
|
||||||
}
|
|
||||||
require(clearData.isNotEmpty()) { "Signing of an empty array is not permitted!" }
|
|
||||||
val signature = Signature.getInstance(signatureScheme.signatureName, signatureScheme.providerName)
|
|
||||||
signature.initSign(privateKey)
|
|
||||||
signature.update(clearData)
|
|
||||||
return signature.sign()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generic way to sign [SignableData] objects with a [PrivateKey].
|
|
||||||
* [SignableData] is a wrapper over the transaction's id (Merkle root) in order to attach extra information, such as
|
|
||||||
* a timestamp or partial and blind signature indicators.
|
|
||||||
* @param keyPair the signer's [KeyPair].
|
|
||||||
* @param signableData a [SignableData] object that adds extra information to a transaction.
|
|
||||||
* @return a [TransactionSignature] object than contains the output of a successful signing, signer's public key and
|
|
||||||
* the signature metadata.
|
|
||||||
* @throws IllegalArgumentException if the signature scheme is not supported for this private key.
|
|
||||||
* @throws InvalidKeyException if the private key is invalid.
|
|
||||||
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
@Throws(InvalidKeyException::class, SignatureException::class)
|
|
||||||
fun doSign(keyPair: KeyPair, signableData: SignableData): TransactionSignature {
|
|
||||||
val sigKey: SignatureScheme = findSignatureScheme(keyPair.private)
|
|
||||||
val sigMetaData: SignatureScheme = findSignatureScheme(keyPair.public)
|
|
||||||
require(sigKey == sigMetaData) {
|
|
||||||
"Metadata schemeCodeName: ${sigMetaData.schemeCodeName} is not aligned with the key type: ${sigKey.schemeCodeName}."
|
|
||||||
}
|
|
||||||
val signatureBytes = doSign(sigKey.schemeCodeName, keyPair.private, signableData.serialize().bytes)
|
|
||||||
return TransactionSignature(signatureBytes, keyPair.public, signableData.signatureMetadata)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
package net.corda.deterministic.crypto
|
|
||||||
|
|
||||||
import net.corda.core.crypto.DigestService
|
|
||||||
import net.corda.core.crypto.MerkleTree
|
|
||||||
import net.corda.core.crypto.SecureHash
|
|
||||||
import org.junit.Assert.assertEquals
|
|
||||||
import org.junit.Test
|
|
||||||
|
|
||||||
class MerkleTreeTest {
|
|
||||||
private fun leafs(algorithm : String) : List<SecureHash> =
|
|
||||||
listOf(SecureHash.allOnesHashFor(algorithm), SecureHash.zeroHashFor(algorithm))
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testCreate() {
|
|
||||||
val merkle = MerkleTree.getMerkleTree(leafs(SecureHash.SHA2_256), DigestService.sha2_256)
|
|
||||||
assertEquals(SecureHash.create("A5DE9B714ACCD8AFAAABF1CBD6E1014C9D07FF95C2AE154D91EC68485B31E7B5"), merkle.hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun `test create SHA2-384`() {
|
|
||||||
val merkle = MerkleTree.getMerkleTree(leafs(SecureHash.SHA2_384), DigestService.sha2_384)
|
|
||||||
assertEquals(SecureHash.create("SHA-384:2B83D37859E3665D7C239964D769CF950EE6478C13E4CA2D6643C23B6C4EAE035C88F654D22E0D65E7CA40BAE4F3718F"), merkle.hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun `test create SHA2-256 to SHA2-384`() {
|
|
||||||
val merkle = MerkleTree.getMerkleTree(leafs(SecureHash.SHA2_256), DigestService.sha2_384)
|
|
||||||
assertEquals(SecureHash.create("SHA-384:02A4E8EA5AA4BBAFE80C0E7127B15994B84030BE8616EA2A0127D85203CF34221403635C08084A6BDDB1DB06333F0A49"), merkle.hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Test(timeout=300_000)
|
|
||||||
// fun testCreateSHA3256() {
|
|
||||||
// val merkle = MerkleTree.getMerkleTree(listOf(SecureHash.allOnesHashFor(SecureHash.SHA3_256),
|
|
||||||
// SecureHash.zeroHashFor(SecureHash.SHA3_256)), DigestService.sha3_256)
|
|
||||||
// assertEquals(SecureHash.create("SHA3-256:80673DBEEC8F6761ACBB121E7E45F61D4279CCD8B8E2231741ECD0716F4C9EDC"), merkle.hash)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Test(timeout=300_000)
|
|
||||||
// fun testCreateSHA2256toSHA3256() {
|
|
||||||
// val merkle = MerkleTree.getMerkleTree(listOf(SecureHash.allOnesHash, SecureHash.zeroHash), DigestService.sha3_256)
|
|
||||||
// assertEquals(SecureHash.create("SHA3-256:80673DBEEC8F6761ACBB121E7E45F61D4279CCD8B8E2231741ECD0716F4C9EDC"), merkle.hash)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// @Test(timeout=300_000)
|
|
||||||
// fun testCreateSHA3256toSHA2256() {
|
|
||||||
// val merkle = MerkleTree.getMerkleTree(listOf(SecureHash.allOnesHashFor(SecureHash.SHA3_256),
|
|
||||||
// SecureHash.zeroHashFor(SecureHash.SHA3_256)), DigestService.sha2_256)
|
|
||||||
// assertEquals(SecureHash.create("A5DE9B714ACCD8AFAAABF1CBD6E1014C9D07FF95C2AE154D91EC68485B31E7B5"), merkle.hash)
|
|
||||||
// }
|
|
||||||
}
|
|
@ -1,42 +0,0 @@
|
|||||||
package net.corda.deterministic.crypto
|
|
||||||
|
|
||||||
import net.corda.core.crypto.SecureHash
|
|
||||||
import org.bouncycastle.util.encoders.Hex
|
|
||||||
import org.junit.Assert.*
|
|
||||||
import org.junit.Test
|
|
||||||
import java.security.MessageDigest
|
|
||||||
|
|
||||||
class SecureHashTest {
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testSHA256() {
|
|
||||||
val hash = SecureHash.sha256(byteArrayOf(0x64, -0x13, 0x42, 0x3a))
|
|
||||||
assertEquals(SecureHash.create("6D1687C143DF792A011A1E80670A4E4E0C25D0D87A39514409B1ABFC2043581F"), hash)
|
|
||||||
assertEquals("6D1687C143DF792A011A1E80670A4E4E0C25D0D87A39514409B1ABFC2043581F", hash.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testPrefix() {
|
|
||||||
val data = byteArrayOf(0x7d, 0x03, -0x21, 0x32, 0x56, 0x47)
|
|
||||||
val digest = data.digestFor("SHA-256")
|
|
||||||
val prefix = SecureHash.sha256(data).prefixChars(8)
|
|
||||||
assertEquals(Hex.toHexString(digest).substring(0, 8).toUpperCase(), prefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testConcat() {
|
|
||||||
val hash1 = SecureHash.sha256(byteArrayOf(0x7d, 0x03, -0x21, 0x32, 0x56, 0x47))
|
|
||||||
val hash2 = SecureHash.sha256(byteArrayOf(0x63, 0x01, 0x7f, -0x29, 0x1e, 0x3c))
|
|
||||||
val combined = hash1.hashConcat(hash2)
|
|
||||||
assertArrayEquals((hash1.bytes + hash2.bytes).digestFor("SHA-256"), combined.bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testConstants() {
|
|
||||||
assertArrayEquals(SecureHash.zeroHash.bytes, ByteArray(32))
|
|
||||||
assertArrayEquals(SecureHash.allOnesHash.bytes, ByteArray(32) { 0xFF.toByte() })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun ByteArray.digestFor(algorithm: String): ByteArray {
|
|
||||||
return MessageDigest.getInstance(algorithm).digest(this)
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
package net.corda.deterministic.crypto
|
|
||||||
|
|
||||||
import net.corda.core.crypto.CordaSecurityProvider
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
|
||||||
import org.junit.Test
|
|
||||||
import java.security.NoSuchAlgorithmException
|
|
||||||
import java.security.SecureRandom
|
|
||||||
import kotlin.test.assertFailsWith
|
|
||||||
|
|
||||||
class SecureRandomTest {
|
|
||||||
private companion object {
|
|
||||||
init {
|
|
||||||
CordaSecurityProvider()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun testNoCordaPRNG() {
|
|
||||||
val error = assertFailsWith<NoSuchAlgorithmException> { SecureRandom.getInstance("CordaPRNG") }
|
|
||||||
assertThat(error).hasMessage("CordaPRNG SecureRandom not available")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,143 +0,0 @@
|
|||||||
package net.corda.deterministic.crypto
|
|
||||||
|
|
||||||
import net.corda.core.crypto.*
|
|
||||||
import net.corda.deterministic.KeyStoreProvider
|
|
||||||
import net.corda.deterministic.CheatingSecurityProvider
|
|
||||||
import net.corda.deterministic.verifier.LocalSerializationRule
|
|
||||||
import org.junit.*
|
|
||||||
import org.junit.rules.RuleChain
|
|
||||||
import java.security.*
|
|
||||||
import kotlin.test.*
|
|
||||||
|
|
||||||
class TransactionSignatureTest {
|
|
||||||
companion object {
|
|
||||||
private const val KEYSTORE_PASSWORD = "deterministic"
|
|
||||||
private val testBytes = "12345678901234567890123456789012".toByteArray()
|
|
||||||
|
|
||||||
private val keyStoreProvider = KeyStoreProvider("keystore/txsignature.pfx", KEYSTORE_PASSWORD)
|
|
||||||
private lateinit var keyPair: KeyPair
|
|
||||||
|
|
||||||
@ClassRule
|
|
||||||
@JvmField
|
|
||||||
val rules: RuleChain = RuleChain.outerRule(LocalSerializationRule(TransactionSignatureTest::class))
|
|
||||||
.around(keyStoreProvider)
|
|
||||||
|
|
||||||
@BeforeClass
|
|
||||||
@JvmStatic
|
|
||||||
fun setupClass() {
|
|
||||||
keyPair = keyStoreProvider.getKeyPair("tx")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Valid sign and verify. */
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun `Signature metadata full sign and verify`() {
|
|
||||||
// Create a SignableData object.
|
|
||||||
val signableData = SignableData(testBytes.sha256(), SignatureMetadata(1, Crypto.findSignatureScheme(keyPair.public).schemeNumberID))
|
|
||||||
|
|
||||||
// Sign the meta object.
|
|
||||||
val transactionSignature: TransactionSignature = CheatingSecurityProvider().use {
|
|
||||||
CryptoSignUtils.doSign(keyPair, signableData)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check auto-verification.
|
|
||||||
assertTrue(transactionSignature.verify(testBytes.sha256()))
|
|
||||||
|
|
||||||
// Check manual verification.
|
|
||||||
assertTrue(Crypto.doVerify(testBytes.sha256(), transactionSignature))
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Verification should fail; corrupted metadata - clearData (Merkle root) has changed. */
|
|
||||||
@Test(expected = SignatureException::class)
|
|
||||||
fun `Signature metadata full failure clearData has changed`() {
|
|
||||||
val signableData = SignableData(testBytes.sha256(), SignatureMetadata(1, Crypto.findSignatureScheme(keyPair.public).schemeNumberID))
|
|
||||||
val transactionSignature = CheatingSecurityProvider().use {
|
|
||||||
CryptoSignUtils.doSign(keyPair, signableData)
|
|
||||||
}
|
|
||||||
Crypto.doVerify((testBytes + testBytes).sha256(), transactionSignature)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun `Verify multi-tx signature`() {
|
|
||||||
// Deterministically create 5 txIds.
|
|
||||||
val txIds: List<SecureHash> = IntRange(0, 4).map { byteArrayOf(it.toByte()).sha256() }
|
|
||||||
// Multi-tx signature.
|
|
||||||
val txSignature = signMultipleTx(txIds, keyPair)
|
|
||||||
|
|
||||||
// The hash of all txIds are used as leaves.
|
|
||||||
val merkleTree = MerkleTree.getMerkleTree(txIds.map { it.sha256() }, DigestService.default)
|
|
||||||
|
|
||||||
// We haven't added the partial tree yet.
|
|
||||||
assertNull(txSignature.partialMerkleTree)
|
|
||||||
// Because partial tree is still null, but we signed over a block of txs, verifying a single tx will fail.
|
|
||||||
assertFailsWith<SignatureException> { Crypto.doVerify(txIds[3], txSignature) }
|
|
||||||
|
|
||||||
// Create a partial tree for one tx.
|
|
||||||
val pmt = PartialMerkleTree.build(merkleTree, listOf(txIds[0].sha256()))
|
|
||||||
// Add the partial Merkle tree to the tx signature.
|
|
||||||
val txSignatureWithTree = TransactionSignature(txSignature.bytes, txSignature.by, txSignature.signatureMetadata, pmt)
|
|
||||||
|
|
||||||
// Verify the corresponding txId with every possible way.
|
|
||||||
assertTrue(Crypto.doVerify(txIds[0], txSignatureWithTree))
|
|
||||||
assertTrue(txSignatureWithTree.verify(txIds[0]))
|
|
||||||
assertTrue(Crypto.isValid(txIds[0], txSignatureWithTree))
|
|
||||||
assertTrue(txSignatureWithTree.isValid(txIds[0]))
|
|
||||||
|
|
||||||
// Verify the rest txs in the block, which are not included in the partial Merkle tree.
|
|
||||||
txIds.subList(1, txIds.size).forEach {
|
|
||||||
assertFailsWith<IllegalArgumentException> { Crypto.doVerify(it, txSignatureWithTree) }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that the Merkle tree consists of hash(txId), not txId.
|
|
||||||
assertFailsWith<MerkleTreeException> { PartialMerkleTree.build(merkleTree, listOf(txIds[0])) }
|
|
||||||
|
|
||||||
// What if we send the Full tree. This could be used if notaries didn't want to create a per tx partial tree.
|
|
||||||
// Create a partial tree for all txs, thus all leaves are included.
|
|
||||||
val pmtFull = PartialMerkleTree.build(merkleTree, txIds.map { it.sha256() })
|
|
||||||
// Add the partial Merkle tree to the tx.
|
|
||||||
val txSignatureWithFullTree = TransactionSignature(txSignature.bytes, txSignature.by, txSignature.signatureMetadata, pmtFull)
|
|
||||||
|
|
||||||
// All txs can be verified, as they are all included in the provided partial tree.
|
|
||||||
txIds.forEach {
|
|
||||||
assertTrue(Crypto.doVerify(it, txSignatureWithFullTree))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun `Verify one-tx signature`() {
|
|
||||||
val txId = "aTransaction".toByteArray().sha256()
|
|
||||||
// One-tx signature.
|
|
||||||
val txSignature = try {
|
|
||||||
signOneTx(txId, keyPair)
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
e.cause?.printStackTrace()
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
|
|
||||||
// partialMerkleTree should be null.
|
|
||||||
assertNull(txSignature.partialMerkleTree)
|
|
||||||
// Verify the corresponding txId with every possible way.
|
|
||||||
assertTrue(Crypto.doVerify(txId, txSignature))
|
|
||||||
assertTrue(txSignature.verify(txId))
|
|
||||||
assertTrue(Crypto.isValid(txId, txSignature))
|
|
||||||
assertTrue(txSignature.isValid(txId))
|
|
||||||
|
|
||||||
// We signed the txId itself, not its hash (because it was a signature over one tx only and no partial tree has been received).
|
|
||||||
assertFailsWith<SignatureException> { Crypto.doVerify(txId.sha256(), txSignature) }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a TransactionSignature over the Merkle root, but the partial tree is null.
|
|
||||||
private fun signMultipleTx(txIds: List<SecureHash>, keyPair: KeyPair): TransactionSignature {
|
|
||||||
val merkleTreeRoot = MerkleTree.getMerkleTree(txIds.map { it.sha256() }, DigestService.default).hash
|
|
||||||
return signOneTx(merkleTreeRoot, keyPair)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a TransactionSignature over one SecureHash.
|
|
||||||
// Note that if one tx is to be signed, we don't create a Merkle tree and we directly sign over the txId.
|
|
||||||
private fun signOneTx(txId: SecureHash, keyPair: KeyPair): TransactionSignature {
|
|
||||||
val signableData = SignableData(txId, SignatureMetadata(3, Crypto.findSignatureScheme(keyPair.public).schemeNumberID))
|
|
||||||
return CheatingSecurityProvider().use {
|
|
||||||
CryptoSignUtils.doSign(keyPair, signableData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
package net.corda.deterministic.transactions
|
|
||||||
|
|
||||||
import net.corda.core.crypto.SecureHash
|
|
||||||
import net.corda.core.crypto.TransactionSignature
|
|
||||||
import net.corda.core.transactions.TransactionWithSignatures
|
|
||||||
import org.junit.Test
|
|
||||||
import java.security.PublicKey
|
|
||||||
|
|
||||||
class TransactionWithSignaturesTest {
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun txWithSigs() {
|
|
||||||
val tx = object : TransactionWithSignatures {
|
|
||||||
override val id: SecureHash
|
|
||||||
get() = SecureHash.zeroHash
|
|
||||||
override val requiredSigningKeys: Set<PublicKey>
|
|
||||||
get() = emptySet()
|
|
||||||
override val sigs: List<TransactionSignature>
|
|
||||||
get() = emptyList()
|
|
||||||
|
|
||||||
override fun getKeyDescriptions(keys: Set<PublicKey>): List<String> {
|
|
||||||
return emptyList()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tx.verifyRequiredSignatures()
|
|
||||||
tx.checkSignaturesAreValid()
|
|
||||||
tx.getMissingSigners()
|
|
||||||
tx.verifySignaturesExcept()
|
|
||||||
tx.verifySignaturesExcept(emptySet())
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
package net.corda.deterministic.txverify
|
|
||||||
|
|
||||||
import net.corda.deterministic.bytesOfResource
|
|
||||||
import net.corda.deterministic.verifier.LocalSerializationRule
|
|
||||||
import net.corda.deterministic.verifier.verifyTransaction
|
|
||||||
import net.corda.finance.contracts.asset.Cash.Commands.*
|
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
|
||||||
import org.junit.ClassRule
|
|
||||||
import org.junit.Test
|
|
||||||
import kotlin.test.assertFailsWith
|
|
||||||
|
|
||||||
class VerifyTransactionTest {
|
|
||||||
companion object {
|
|
||||||
@ClassRule
|
|
||||||
@JvmField
|
|
||||||
val serialization = LocalSerializationRule(VerifyTransactionTest::class)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun success() {
|
|
||||||
verifyTransaction(bytesOfResource("txverify/tx-success.bin"))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
|
||||||
fun failure() {
|
|
||||||
val e = assertFailsWith<Exception> { verifyTransaction(bytesOfResource("txverify/tx-failure.bin")) }
|
|
||||||
assertThat(e).hasMessageContaining("Required ${Move::class.java.canonicalName} command")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Configuration status="info">
|
|
||||||
<Appenders>
|
|
||||||
<Console name="Console-Appender" target="SYSTEM_OUT">
|
|
||||||
<PatternLayout pattern="%date %highlight{%level %c{1}.%method - %msg%n}{INFO=white,WARN=red,FATAL=bright red}"/>
|
|
||||||
</Console>
|
|
||||||
</Appenders>
|
|
||||||
|
|
||||||
<Loggers>
|
|
||||||
<Root level="info">
|
|
||||||
<AppenderRef ref="Console-Appender"/>
|
|
||||||
</Root>
|
|
||||||
</Loggers>
|
|
||||||
</Configuration>
|
|
@ -1,56 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'java-library'
|
|
||||||
id 'net.corda.plugins.publish-utils'
|
|
||||||
id 'com.jfrog.artifactory'
|
|
||||||
id 'idea'
|
|
||||||
}
|
|
||||||
apply from: "${rootProject.projectDir}/deterministic.gradle"
|
|
||||||
|
|
||||||
description 'Test utilities for deterministic contract verification'
|
|
||||||
|
|
||||||
configurations {
|
|
||||||
deterministicArtifacts {
|
|
||||||
canBeResolved = false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compile against the deterministic artifacts to ensure that we use only the deterministic API subset.
|
|
||||||
compileOnly.extendsFrom deterministicArtifacts
|
|
||||||
runtimeArtifacts.extendsFrom api
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
deterministicArtifacts project(path: ':serialization-deterministic', configuration: 'deterministicArtifacts')
|
|
||||||
deterministicArtifacts project(path: ':core-deterministic', configuration: 'deterministicArtifacts')
|
|
||||||
|
|
||||||
runtimeArtifacts project(':serialization')
|
|
||||||
runtimeArtifacts project(':core')
|
|
||||||
|
|
||||||
api "junit:junit:$junit_version"
|
|
||||||
runtimeOnly "org.junit.vintage:junit-vintage-engine:$junit_vintage_version"
|
|
||||||
}
|
|
||||||
|
|
||||||
jar {
|
|
||||||
archiveBaseName = 'corda-deterministic-verifier'
|
|
||||||
}
|
|
||||||
|
|
||||||
artifacts {
|
|
||||||
deterministicArtifacts jar
|
|
||||||
runtimeArtifacts jar
|
|
||||||
publish jar
|
|
||||||
}
|
|
||||||
|
|
||||||
publish {
|
|
||||||
// Our published POM will contain dependencies on the non-deterministic Corda artifacts.
|
|
||||||
dependenciesFrom(configurations.runtimeArtifacts) {
|
|
||||||
defaultScope = 'compile'
|
|
||||||
}
|
|
||||||
name jar.archiveBaseName.get()
|
|
||||||
}
|
|
||||||
|
|
||||||
idea {
|
|
||||||
module {
|
|
||||||
if (project.hasProperty("deterministic_idea_sdk")) {
|
|
||||||
jdkName project.property("deterministic_idea_sdk") as String
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
package net.corda.deterministic.verifier
|
|
||||||
|
|
||||||
import net.corda.core.serialization.SerializationContext
|
|
||||||
import net.corda.core.serialization.SerializationContext.UseCase.P2P
|
|
||||||
import net.corda.core.serialization.SerializationCustomSerializer
|
|
||||||
import net.corda.core.serialization.SerializationWhitelist
|
|
||||||
import net.corda.core.serialization.internal.SerializationEnvironment
|
|
||||||
import net.corda.core.serialization.internal._driverSerializationEnv
|
|
||||||
import net.corda.serialization.internal.*
|
|
||||||
import net.corda.serialization.internal.amqp.*
|
|
||||||
import org.junit.rules.TestRule
|
|
||||||
import org.junit.runner.Description
|
|
||||||
import org.junit.runners.model.Statement
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
import kotlin.reflect.jvm.jvmName
|
|
||||||
|
|
||||||
class LocalSerializationRule(private val label: String) : TestRule {
|
|
||||||
constructor(klass: KClass<*>) : this(klass.jvmName)
|
|
||||||
|
|
||||||
private companion object {
|
|
||||||
private val AMQP_P2P_CONTEXT = SerializationContextImpl(
|
|
||||||
amqpMagic,
|
|
||||||
LocalSerializationRule::class.java.classLoader,
|
|
||||||
GlobalTransientClassWhiteList(BuiltInExceptionsWhitelist()),
|
|
||||||
emptyMap(),
|
|
||||||
true,
|
|
||||||
P2P,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun apply(base: Statement, description: Description): Statement {
|
|
||||||
return object : Statement() {
|
|
||||||
override fun evaluate() {
|
|
||||||
init()
|
|
||||||
try {
|
|
||||||
base.evaluate()
|
|
||||||
} finally {
|
|
||||||
clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun reset() {
|
|
||||||
clear()
|
|
||||||
init()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun init() {
|
|
||||||
_driverSerializationEnv.set(createTestSerializationEnv())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun clear() {
|
|
||||||
_driverSerializationEnv.set(null)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createTestSerializationEnv(): SerializationEnvironment {
|
|
||||||
val factory = SerializationFactoryImpl(mutableMapOf()).apply {
|
|
||||||
registerScheme(AMQPSerializationScheme(emptySet(), emptySet(), AccessOrderLinkedHashMap(128)))
|
|
||||||
}
|
|
||||||
return SerializationEnvironment.with(factory, AMQP_P2P_CONTEXT)
|
|
||||||
}
|
|
||||||
|
|
||||||
private class AMQPSerializationScheme(
|
|
||||||
cordappCustomSerializers: Set<SerializationCustomSerializer<*, *>>,
|
|
||||||
cordappSerializationWhitelists: Set<SerializationWhitelist>,
|
|
||||||
serializerFactoriesForContexts: AccessOrderLinkedHashMap<SerializationFactoryCacheKey, SerializerFactory>
|
|
||||||
) : AbstractAMQPSerializationScheme(cordappCustomSerializers, cordappSerializationWhitelists, serializerFactoriesForContexts) {
|
|
||||||
override fun rpcServerSerializerFactory(context: SerializationContext): SerializerFactory {
|
|
||||||
throw UnsupportedOperationException()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun rpcClientSerializerFactory(context: SerializationContext): SerializerFactory {
|
|
||||||
throw UnsupportedOperationException()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun canDeserializeVersion(magic: CordaSerializationMagic, target: SerializationContext.UseCase): Boolean {
|
|
||||||
return canDeserializeVersion(magic) && target == P2P
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package net.corda.deterministic.verifier
|
|
||||||
|
|
||||||
import net.corda.core.contracts.ContractClassName
|
|
||||||
import net.corda.core.crypto.SecureHash
|
|
||||||
import net.corda.core.identity.Party
|
|
||||||
import net.corda.core.internal.AbstractAttachment
|
|
||||||
import net.corda.core.serialization.CordaSerializable
|
|
||||||
import java.security.PublicKey
|
|
||||||
|
|
||||||
// A valid zip file with 1 entry.
|
|
||||||
val simpleZip = byteArrayOf(80, 75, 3, 4, 20, 0, 8, 8, 8, 0, 15, 113, 79, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 4, 0, 47, 97, -2, -54, 0, 0, 75, 4, 0, 80, 75, 7, 8, 67, -66, -73, -24, 3, 0, 0, 0, 1, 0, 0, 0, 80, 75, 1, 2, 20, 0, 20, 0, 8, 8, 8, 0, 15, 113, 79, 78, 67, -66, -73, -24, 3, 0, 0, 0, 1, 0, 0, 0, 2, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47, 97, -2, -54, 0, 0, 80, 75, 5, 6, 0, 0, 0, 0, 1, 0, 1, 0, 52, 0, 0, 0, 55, 0, 0, 0, 0, 0)
|
|
||||||
|
|
||||||
@CordaSerializable
|
|
||||||
class MockContractAttachment(
|
|
||||||
override val id: SecureHash = SecureHash.zeroHash,
|
|
||||||
val contract: ContractClassName,
|
|
||||||
override val signerKeys: List<PublicKey> = emptyList(),
|
|
||||||
override val signers: List<Party> = emptyList()
|
|
||||||
) : AbstractAttachment({ simpleZip }, "app")
|
|
@ -1,6 +0,0 @@
|
|||||||
@file:JvmName("SampleData")
|
|
||||||
package net.corda.deterministic.verifier
|
|
||||||
|
|
||||||
import net.corda.core.contracts.TypeOnlyCommandData
|
|
||||||
|
|
||||||
object SampleCommandData : TypeOnlyCommandData()
|
|
@ -1,35 +0,0 @@
|
|||||||
package net.corda.deterministic.verifier
|
|
||||||
|
|
||||||
import net.corda.core.contracts.Attachment
|
|
||||||
import net.corda.core.contracts.ContractAttachment
|
|
||||||
import net.corda.core.internal.DEPLOYED_CORDAPP_UPLOADER
|
|
||||||
import net.corda.core.internal.toLtxDjvmInternal
|
|
||||||
import net.corda.core.node.NetworkParameters
|
|
||||||
import net.corda.core.serialization.CordaSerializable
|
|
||||||
import net.corda.core.serialization.SerializedBytes
|
|
||||||
import net.corda.core.serialization.deserialize
|
|
||||||
import net.corda.core.transactions.LedgerTransaction
|
|
||||||
import net.corda.core.transactions.WireTransaction
|
|
||||||
|
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
|
||||||
//TODO the use of deprecated toLedgerTransaction need to be revisited as resolveContractAttachment requires attachments of the transactions which created input states...
|
|
||||||
//TODO ...to check contract version non downgrade rule, currently dummy Attachment if not fund is used which sets contract version to '1'
|
|
||||||
@CordaSerializable
|
|
||||||
class TransactionVerificationRequest(val wtxToVerify: SerializedBytes<WireTransaction>,
|
|
||||||
val dependencies: Array<SerializedBytes<WireTransaction>>,
|
|
||||||
val attachments: Array<ByteArray>,
|
|
||||||
val networkParameters: SerializedBytes<NetworkParameters>) {
|
|
||||||
fun toLedgerTransaction(): LedgerTransaction {
|
|
||||||
val deps = dependencies.map { it.deserialize() }.associateBy(WireTransaction::id)
|
|
||||||
val attachments = attachments.map { it.deserialize<Attachment>() }
|
|
||||||
val attachmentMap = attachments
|
|
||||||
.mapNotNull { it as? MockContractAttachment }
|
|
||||||
.associateBy(Attachment::id) { ContractAttachment(it, it.contract, uploader = DEPLOYED_CORDAPP_UPLOADER) }
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
return wtxToVerify.deserialize().toLtxDjvmInternal(
|
|
||||||
resolveAttachment = { attachmentMap[it] },
|
|
||||||
resolveStateRef = { deps[it.txhash]?.outputs?.get(it.index) },
|
|
||||||
resolveParameters = { networkParameters.deserialize() }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
@file:JvmName("Verifier")
|
|
||||||
package net.corda.deterministic.verifier
|
|
||||||
|
|
||||||
import net.corda.core.serialization.deserialize
|
|
||||||
import net.corda.core.transactions.LedgerTransaction
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We assume the signatures were already checked outside the sandbox: the purpose of this code
|
|
||||||
* is simply to check the sensitive, app-specific parts of a transaction.
|
|
||||||
*
|
|
||||||
* TODO: Transaction data is meant to be encrypted under an enclave-private key.
|
|
||||||
*/
|
|
||||||
@Throws(Exception::class)
|
|
||||||
fun verifyTransaction(reqBytes: ByteArray) {
|
|
||||||
deserialize(reqBytes).verify()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun deserialize(reqBytes: ByteArray): LedgerTransaction {
|
|
||||||
return reqBytes.deserialize<TransactionVerificationRequest>()
|
|
||||||
.toLedgerTransaction()
|
|
||||||
}
|
|
@ -92,6 +92,8 @@ dependencies {
|
|||||||
smokeTestCompile project(':smoke-test-utils')
|
smokeTestCompile project(':smoke-test-utils')
|
||||||
smokeTestCompile "org.assertj:assertj-core:${assertj_version}"
|
smokeTestCompile "org.assertj:assertj-core:${assertj_version}"
|
||||||
|
|
||||||
|
// used by FinalityFlowTests
|
||||||
|
testCompile project(':testing:cordapps:cashobservers')
|
||||||
}
|
}
|
||||||
|
|
||||||
configurations {
|
configurations {
|
||||||
|
@ -10,6 +10,7 @@ import net.corda.core.crypto.SecureHash.Companion.allOnesHash
|
|||||||
import net.corda.core.crypto.SecureHash.Companion.zeroHash
|
import net.corda.core.crypto.SecureHash.Companion.zeroHash
|
||||||
import net.corda.core.crypto.SignableData
|
import net.corda.core.crypto.SignableData
|
||||||
import net.corda.core.crypto.SignatureMetadata
|
import net.corda.core.crypto.SignatureMetadata
|
||||||
|
import net.corda.core.crypto.sign
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.canBeTransitionedFrom
|
import net.corda.core.internal.canBeTransitionedFrom
|
||||||
@ -49,6 +50,7 @@ class ConstraintsPropagationTests {
|
|||||||
val testSerialization = SerializationEnvironmentRule()
|
val testSerialization = SerializationEnvironmentRule()
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
|
val DUMMY_NOTARY_IDENTITY = TestIdentity(DUMMY_NOTARY_NAME, 20)
|
||||||
val DUMMY_NOTARY = TestIdentity(DUMMY_NOTARY_NAME, 20).party
|
val DUMMY_NOTARY = TestIdentity(DUMMY_NOTARY_NAME, 20).party
|
||||||
val ALICE = TestIdentity(CordaX500Name("ALICE", "London", "GB"))
|
val ALICE = TestIdentity(CordaX500Name("ALICE", "London", "GB"))
|
||||||
val ALICE_PARTY get() = ALICE.party
|
val ALICE_PARTY get() = ALICE.party
|
||||||
@ -376,7 +378,8 @@ class ConstraintsPropagationTests {
|
|||||||
requireSupportedHashType(wireTransaction)
|
requireSupportedHashType(wireTransaction)
|
||||||
val nodeKey = ALICE_PUBKEY
|
val nodeKey = ALICE_PUBKEY
|
||||||
val sigs = listOf(keyManagementService.sign(
|
val sigs = listOf(keyManagementService.sign(
|
||||||
SignableData(wireTransaction.id, SignatureMetadata(4, Crypto.findSignatureScheme(nodeKey).schemeNumberID)), nodeKey))
|
SignableData(wireTransaction.id, SignatureMetadata(4, Crypto.findSignatureScheme(nodeKey).schemeNumberID)), nodeKey),
|
||||||
|
DUMMY_NOTARY_IDENTITY.keyPair.sign(SignableData(wireTransaction.id, SignatureMetadata(4, Crypto.findSignatureScheme(DUMMY_NOTARY_IDENTITY.publicKey).schemeNumberID))))
|
||||||
recordTransactions(SignedTransaction(wireTransaction, sigs))
|
recordTransactions(SignedTransaction(wireTransaction, sigs))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ import java.util.*
|
|||||||
class ContractUpgradeFlowTest : WithContracts, WithFinality {
|
class ContractUpgradeFlowTest : WithContracts, WithFinality {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val classMockNet = InternalMockNetwork(cordappsForAllNodes = listOf(FINANCE_CONTRACTS_CORDAPP, DUMMY_CONTRACTS_CORDAPP, enclosedCordapp()))
|
private val classMockNet = InternalMockNetwork(cordappsForAllNodes = listOf(FINANCE_CONTRACTS_CORDAPP, FINANCE_WORKFLOWS_CORDAPP, DUMMY_CONTRACTS_CORDAPP, enclosedCordapp()))
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@AfterClass
|
@AfterClass
|
||||||
|
@ -1,32 +1,95 @@
|
|||||||
package net.corda.coretests.flows
|
package net.corda.coretests.flows
|
||||||
|
|
||||||
|
import co.paralleluniverse.fibers.Suspendable
|
||||||
import com.natpryce.hamkrest.and
|
import com.natpryce.hamkrest.and
|
||||||
import com.natpryce.hamkrest.assertion.assertThat
|
import com.natpryce.hamkrest.assertion.assertThat
|
||||||
|
import net.corda.core.contracts.Amount
|
||||||
|
import net.corda.core.contracts.PartyAndReference
|
||||||
|
import net.corda.core.contracts.StateAndContract
|
||||||
|
import net.corda.core.contracts.StateAndRef
|
||||||
|
import net.corda.core.contracts.TransactionVerificationException
|
||||||
|
import net.corda.core.crypto.SecureHash
|
||||||
|
import net.corda.core.crypto.TransactionSignature
|
||||||
import net.corda.core.flows.FinalityFlow
|
import net.corda.core.flows.FinalityFlow
|
||||||
|
import net.corda.core.flows.FlowException
|
||||||
|
import net.corda.core.flows.FlowLogic
|
||||||
|
import net.corda.core.flows.FlowSession
|
||||||
|
import net.corda.core.flows.InitiatedBy
|
||||||
|
import net.corda.core.flows.InitiatingFlow
|
||||||
|
import net.corda.core.flows.NotaryError
|
||||||
|
import net.corda.core.flows.NotaryException
|
||||||
|
import net.corda.core.flows.NotarySigCheck
|
||||||
|
import net.corda.core.flows.ReceiveFinalityFlow
|
||||||
|
import net.corda.core.flows.ReceiveTransactionFlow
|
||||||
|
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
|
import net.corda.core.identity.Party
|
||||||
|
import net.corda.core.internal.FetchDataFlow
|
||||||
|
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.transactions.SignedTransaction
|
import net.corda.core.transactions.SignedTransaction
|
||||||
import net.corda.core.transactions.TransactionBuilder
|
import net.corda.core.transactions.TransactionBuilder
|
||||||
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import net.corda.core.utilities.getOrThrow
|
import net.corda.core.utilities.getOrThrow
|
||||||
import net.corda.coretests.flows.WithFinality.FinalityInvoker
|
import net.corda.core.utilities.unwrap
|
||||||
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.coretesting.internal.matchers.flow.willReturn
|
import net.corda.coretesting.internal.matchers.flow.willReturn
|
||||||
import net.corda.coretesting.internal.matchers.flow.willThrow
|
import net.corda.coretesting.internal.matchers.flow.willThrow
|
||||||
import net.corda.testing.node.internal.*
|
import net.corda.coretests.flows.WithFinality.FinalityInvoker
|
||||||
|
import net.corda.coretests.flows.WithFinality.OldFinalityInvoker
|
||||||
|
import net.corda.finance.GBP
|
||||||
|
import net.corda.finance.POUNDS
|
||||||
|
import net.corda.finance.contracts.asset.Cash
|
||||||
|
import net.corda.finance.flows.CashIssueFlow
|
||||||
|
import net.corda.finance.flows.CashPaymentFlow
|
||||||
|
import net.corda.finance.issuedBy
|
||||||
|
import net.corda.finance.test.flows.CashIssueWithObserversFlow
|
||||||
|
import net.corda.finance.test.flows.CashPaymentWithObserversFlow
|
||||||
|
import net.corda.node.services.persistence.DBTransactionStorage
|
||||||
|
import net.corda.node.services.persistence.DBTransactionStorageLedgerRecovery.DBReceiverDistributionRecord
|
||||||
|
import net.corda.node.services.persistence.DBTransactionStorageLedgerRecovery.DBSenderDistributionRecord
|
||||||
|
import net.corda.node.services.persistence.HashedDistributionList
|
||||||
|
import net.corda.nodeapi.internal.persistence.CordaPersistence
|
||||||
|
import net.corda.testing.contracts.DummyContract
|
||||||
|
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.TestIdentity
|
||||||
|
import net.corda.testing.core.singleIdentity
|
||||||
|
import net.corda.testing.node.internal.DUMMY_CONTRACTS_CORDAPP
|
||||||
|
import net.corda.testing.node.internal.FINANCE_CONTRACTS_CORDAPP
|
||||||
|
import net.corda.testing.node.internal.FINANCE_WORKFLOWS_CORDAPP
|
||||||
|
import net.corda.testing.node.internal.InternalMockNetwork
|
||||||
|
import net.corda.testing.node.internal.InternalMockNodeParameters
|
||||||
|
import net.corda.testing.node.internal.MOCK_VERSION_INFO
|
||||||
|
import net.corda.testing.node.internal.TestCordappInternal
|
||||||
|
import net.corda.testing.node.internal.TestStartedNode
|
||||||
|
import net.corda.testing.node.internal.cordappWithPackages
|
||||||
|
import net.corda.testing.node.internal.enclosedCordapp
|
||||||
|
import net.corda.testing.node.internal.findCordapp
|
||||||
import org.assertj.core.api.Assertions.assertThat
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
|
import org.junit.Assert.assertNotNull
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import java.sql.SQLException
|
||||||
|
import java.util.Random
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertNull
|
||||||
|
import kotlin.test.fail
|
||||||
|
|
||||||
class FinalityFlowTests : WithFinality {
|
class FinalityFlowTests : WithFinality {
|
||||||
companion object {
|
companion object {
|
||||||
private val CHARLIE = TestIdentity(CHARLIE_NAME, 90).party
|
private val CHARLIE = TestIdentity(CHARLIE_NAME, 90).party
|
||||||
}
|
}
|
||||||
|
|
||||||
override val mockNet = InternalMockNetwork(cordappsForAllNodes = listOf(FINANCE_CONTRACTS_CORDAPP, enclosedCordapp(),
|
override val mockNet = InternalMockNetwork(cordappsForAllNodes = setOf(FINANCE_CONTRACTS_CORDAPP, FINANCE_WORKFLOWS_CORDAPP, DUMMY_CONTRACTS_CORDAPP, enclosedCordapp(),
|
||||||
CustomCordapp(targetPlatformVersion = 3, classes = setOf(FinalityFlow::class.java))))
|
findCordapp("net.corda.finance.test.flows")))
|
||||||
|
|
||||||
private val aliceNode = makeNode(ALICE_NAME)
|
private val aliceNode = makeNode(ALICE_NAME)
|
||||||
|
|
||||||
private val notary = mockNet.defaultNotaryIdentity
|
private val notary = mockNet.defaultNotaryIdentity
|
||||||
@ -60,9 +123,8 @@ class FinalityFlowTests : WithFinality {
|
|||||||
fun `allow use of the old API if the CorDapp target version is 3`() {
|
fun `allow use of the old API if the CorDapp target version is 3`() {
|
||||||
val oldBob = createBob(cordapps = listOf(tokenOldCordapp()))
|
val oldBob = createBob(cordapps = listOf(tokenOldCordapp()))
|
||||||
val stx = aliceNode.issuesCashTo(oldBob)
|
val stx = aliceNode.issuesCashTo(oldBob)
|
||||||
@Suppress("DEPRECATION")
|
aliceNode.startFlowAndRunNetwork(OldFinalityInvoker(stx)).resultFuture.getOrThrow()
|
||||||
aliceNode.startFlowAndRunNetwork(FinalityFlow(stx)).resultFuture.getOrThrow()
|
assertThat(oldBob.services.validatedTransactions.getTransaction(stx.id)).isNotNull
|
||||||
assertThat(oldBob.services.validatedTransactions.getTransaction(stx.id)).isNotNull()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
@Test(timeout=300_000)
|
||||||
@ -76,12 +138,497 @@ class FinalityFlowTests : WithFinality {
|
|||||||
oldRecipients = setOf(oldBob.info.singleIdentity())
|
oldRecipients = setOf(oldBob.info.singleIdentity())
|
||||||
)).resultFuture
|
)).resultFuture
|
||||||
resultFuture.getOrThrow()
|
resultFuture.getOrThrow()
|
||||||
assertThat(newCharlie.services.validatedTransactions.getTransaction(stx.id)).isNotNull()
|
assertThat(newCharlie.services.validatedTransactions.getTransaction(stx.id)).isNotNull
|
||||||
assertThat(oldBob.services.validatedTransactions.getTransaction(stx.id)).isNotNull()
|
assertThat(oldBob.services.validatedTransactions.getTransaction(stx.id)).isNotNull
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createBob(cordapps: List<TestCordappInternal> = emptyList()): TestStartedNode {
|
@Test(timeout=300_000)
|
||||||
return mockNet.createNode(InternalMockNodeParameters(legalName = BOB_NAME, additionalCordapps = cordapps))
|
fun `two phase finality flow transaction`() {
|
||||||
|
val bobNode = createBob(platformVersion = PlatformVersionSwitches.TWO_PHASE_FINALITY)
|
||||||
|
|
||||||
|
val stx = aliceNode.startFlow(CashIssueFlow(Amount(1000L, GBP), OpaqueBytes.of(1), notary)).resultFuture.getOrThrow().stx
|
||||||
|
aliceNode.startFlowAndRunNetwork(CashPaymentFlow(Amount(100, GBP), bobNode.info.singleIdentity())).resultFuture.getOrThrow()
|
||||||
|
|
||||||
|
assertThat(aliceNode.services.validatedTransactions.getTransaction(stx.id)).isNotNull
|
||||||
|
assertThat(bobNode.services.validatedTransactions.getTransaction(stx.id)).isNotNull
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `two phase finality flow initiator to pre-2PF peer`() {
|
||||||
|
val bobNode = createBob(platformVersion = PlatformVersionSwitches.TWO_PHASE_FINALITY - 1)
|
||||||
|
|
||||||
|
val stx = aliceNode.startFlow(CashIssueFlow(Amount(1000L, GBP), OpaqueBytes.of(1), notary)).resultFuture.getOrThrow().stx
|
||||||
|
aliceNode.startFlowAndRunNetwork(CashPaymentFlow(Amount(100, GBP), bobNode.info.singleIdentity())).resultFuture.getOrThrow()
|
||||||
|
|
||||||
|
assertThat(aliceNode.services.validatedTransactions.getTransaction(stx.id)).isNotNull
|
||||||
|
assertThat(bobNode.services.validatedTransactions.getTransaction(stx.id)).isNotNull
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `pre-2PF initiator to two phase finality flow peer`() {
|
||||||
|
val bobNode = createBob(platformVersion = PlatformVersionSwitches.TWO_PHASE_FINALITY - 1)
|
||||||
|
|
||||||
|
val stx = bobNode.startFlow(CashIssueFlow(Amount(1000L, GBP), OpaqueBytes.of(1), notary)).resultFuture.getOrThrow().stx
|
||||||
|
bobNode.startFlowAndRunNetwork(CashPaymentFlow(Amount(100, GBP), aliceNode.info.singleIdentity())).resultFuture.getOrThrow()
|
||||||
|
|
||||||
|
assertThat(aliceNode.services.validatedTransactions.getTransaction(stx.id)).isNotNull
|
||||||
|
assertThat(bobNode.services.validatedTransactions.getTransaction(stx.id)).isNotNull
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `two phase finality flow double spend transaction`() {
|
||||||
|
val bobNode = createBob(platformVersion = PlatformVersionSwitches.TWO_PHASE_FINALITY)
|
||||||
|
|
||||||
|
val ref = aliceNode.startFlowAndRunNetwork(IssueFlow(notary)).resultFuture.getOrThrow()
|
||||||
|
val stx = aliceNode.startFlowAndRunNetwork(SpendFlow(ref, bobNode.info.singleIdentity())).resultFuture.getOrThrow()
|
||||||
|
|
||||||
|
val (_, txnStatusAlice) = aliceNode.services.validatedTransactions.getTransactionInternal(stx.id) ?: fail()
|
||||||
|
assertEquals(TransactionStatus.VERIFIED, txnStatusAlice)
|
||||||
|
val (_, txnStatusBob) = bobNode.services.validatedTransactions.getTransactionInternal(stx.id) ?: fail()
|
||||||
|
assertEquals(TransactionStatus.VERIFIED, txnStatusBob)
|
||||||
|
|
||||||
|
try {
|
||||||
|
aliceNode.startFlowAndRunNetwork(SpendFlow(ref, bobNode.info.singleIdentity())).resultFuture.getOrThrow()
|
||||||
|
}
|
||||||
|
catch (e: NotaryException) {
|
||||||
|
val stxId = (e.error as NotaryError.Conflict).txId
|
||||||
|
assertNull(aliceNode.services.validatedTransactions.getTransactionInternal(stxId))
|
||||||
|
// Note: double spend error not propagated to peers by default (corDapp PV = 3)
|
||||||
|
// Un-notarised txn clean-up occurs in ReceiveFinalityFlow upon receipt of UnexpectedFlowEndException
|
||||||
|
assertNull(aliceNode.services.validatedTransactions.getTransactionInternal(stxId))
|
||||||
|
assertTxnRemovedFromDatabase(aliceNode, stxId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `two phase finality flow double spend transaction with double spend handling`() {
|
||||||
|
val bobNode = createBob(platformVersion = PlatformVersionSwitches.TWO_PHASE_FINALITY)
|
||||||
|
|
||||||
|
val ref = aliceNode.startFlowAndRunNetwork(IssueFlow(notary)).resultFuture.getOrThrow()
|
||||||
|
val stx = aliceNode.startFlowAndRunNetwork(SpendFlow(ref, bobNode.info.singleIdentity())).resultFuture.getOrThrow()
|
||||||
|
|
||||||
|
val (_, txnStatusAlice) = aliceNode.services.validatedTransactions.getTransactionInternal(stx.id) ?: fail()
|
||||||
|
assertEquals(TransactionStatus.VERIFIED, txnStatusAlice)
|
||||||
|
val (_, txnStatusBob) = bobNode.services.validatedTransactions.getTransactionInternal(stx.id) ?: fail()
|
||||||
|
assertEquals(TransactionStatus.VERIFIED, txnStatusBob)
|
||||||
|
|
||||||
|
try {
|
||||||
|
aliceNode.startFlowAndRunNetwork(SpendFlow(ref, bobNode.info.singleIdentity(), handlePropagatedNotaryError = true)).resultFuture.getOrThrow()
|
||||||
|
}
|
||||||
|
catch (e: NotaryException) {
|
||||||
|
val stxId = (e.error as NotaryError.Conflict).txId
|
||||||
|
assertNull(aliceNode.services.validatedTransactions.getTransactionInternal(stxId))
|
||||||
|
assertTxnRemovedFromDatabase(aliceNode, stxId)
|
||||||
|
assertNull(bobNode.services.validatedTransactions.getTransactionInternal(stxId))
|
||||||
|
assertTxnRemovedFromDatabase(bobNode, stxId)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
aliceNode.startFlowAndRunNetwork(SpendFlow(ref, bobNode.info.singleIdentity(), handlePropagatedNotaryError = false)).resultFuture.getOrThrow()
|
||||||
|
}
|
||||||
|
catch (e: NotaryException) {
|
||||||
|
val stxId = (e.error as NotaryError.Conflict).txId
|
||||||
|
assertNull(aliceNode.services.validatedTransactions.getTransactionInternal(stxId))
|
||||||
|
assertTxnRemovedFromDatabase(aliceNode, stxId)
|
||||||
|
val (_, txnStatus) = bobNode.services.validatedTransactions.getTransactionInternal(stxId) ?: fail()
|
||||||
|
assertEquals(TransactionStatus.IN_FLIGHT, txnStatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun assertTxnRemovedFromDatabase(node: TestStartedNode, stxId: SecureHash) {
|
||||||
|
val fromDb = node.database.transaction {
|
||||||
|
session.createQuery(
|
||||||
|
"from ${DBTransactionStorage.DBTransaction::class.java.name} where tx_id = :transactionId",
|
||||||
|
DBTransactionStorage.DBTransaction::class.java
|
||||||
|
).setParameter("transactionId", stxId.toString()).resultList
|
||||||
|
}
|
||||||
|
assertEquals(0, fromDb.size)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `two phase finality flow double spend transaction from pre-2PF initiator`() {
|
||||||
|
val bobNode = createBob(platformVersion = PlatformVersionSwitches.TWO_PHASE_FINALITY - 1)
|
||||||
|
|
||||||
|
val ref = bobNode.startFlowAndRunNetwork(IssueFlow(notary)).resultFuture.getOrThrow()
|
||||||
|
val stx = bobNode.startFlowAndRunNetwork(SpendFlow(ref, aliceNode.info.singleIdentity())).resultFuture.getOrThrow()
|
||||||
|
|
||||||
|
val (_, txnStatusAlice) = aliceNode.services.validatedTransactions.getTransactionInternal(stx.id) ?: fail()
|
||||||
|
assertEquals(TransactionStatus.VERIFIED, txnStatusAlice)
|
||||||
|
val (_, txnStatusBob) = bobNode.services.validatedTransactions.getTransactionInternal(stx.id) ?: fail()
|
||||||
|
assertEquals(TransactionStatus.VERIFIED, txnStatusBob)
|
||||||
|
|
||||||
|
try {
|
||||||
|
bobNode.startFlowAndRunNetwork(SpendFlow(ref, aliceNode.info.singleIdentity())).resultFuture.getOrThrow()
|
||||||
|
}
|
||||||
|
catch (e: NotaryException) {
|
||||||
|
val stxId = (e.error as NotaryError.Conflict).txId
|
||||||
|
assertNull(bobNode.services.validatedTransactions.getTransactionInternal(stxId))
|
||||||
|
assertTxnRemovedFromDatabase(bobNode, stxId)
|
||||||
|
assertNull(aliceNode.services.validatedTransactions.getTransactionInternal(stxId))
|
||||||
|
assertTxnRemovedFromDatabase(aliceNode, stxId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `two phase finality flow double spend transaction to pre-2PF peer`() {
|
||||||
|
val bobNode = createBob(platformVersion = PlatformVersionSwitches.TWO_PHASE_FINALITY - 1)
|
||||||
|
|
||||||
|
val ref = aliceNode.startFlowAndRunNetwork(IssueFlow(notary)).resultFuture.getOrThrow()
|
||||||
|
val stx = aliceNode.startFlowAndRunNetwork(SpendFlow(ref, bobNode.info.singleIdentity())).resultFuture.getOrThrow()
|
||||||
|
|
||||||
|
val (_, txnStatusAlice) = aliceNode.services.validatedTransactions.getTransactionInternal(stx.id) ?: fail()
|
||||||
|
assertEquals(TransactionStatus.VERIFIED, txnStatusAlice)
|
||||||
|
val (_, txnStatusBob) = bobNode.services.validatedTransactions.getTransactionInternal(stx.id) ?: fail()
|
||||||
|
assertEquals(TransactionStatus.VERIFIED, txnStatusBob)
|
||||||
|
|
||||||
|
try {
|
||||||
|
aliceNode.startFlowAndRunNetwork(SpendFlow(ref, bobNode.info.singleIdentity())).resultFuture.getOrThrow()
|
||||||
|
}
|
||||||
|
catch (e: NotaryException) {
|
||||||
|
val stxId = (e.error as NotaryError.Conflict).txId
|
||||||
|
assertNull(aliceNode.services.validatedTransactions.getTransactionInternal(stxId))
|
||||||
|
assertTxnRemovedFromDatabase(aliceNode, stxId)
|
||||||
|
assertNull(bobNode.services.validatedTransactions.getTransactionInternal(stxId))
|
||||||
|
assertTxnRemovedFromDatabase(bobNode, stxId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `two phase finality flow speedy spender`() {
|
||||||
|
val bobNode = createBob(platformVersion = PlatformVersionSwitches.TWO_PHASE_FINALITY)
|
||||||
|
|
||||||
|
val ref = aliceNode.startFlowAndRunNetwork(IssueFlow(notary)).resultFuture.getOrThrow()
|
||||||
|
val notarisedStxn1 = aliceNode.startFlowAndRunNetwork(SpeedySpendFlow(ref, bobNode.info.singleIdentity())).resultFuture.getOrThrow()
|
||||||
|
|
||||||
|
val (_, txnStatusAlice) = aliceNode.services.validatedTransactions.getTransactionInternal(notarisedStxn1.id) ?: fail()
|
||||||
|
assertEquals(TransactionStatus.VERIFIED, txnStatusAlice)
|
||||||
|
val (_, txnStatusBob) = bobNode.services.validatedTransactions.getTransactionInternal(notarisedStxn1.id) ?: fail()
|
||||||
|
assertEquals(TransactionStatus.IN_FLIGHT, txnStatusBob)
|
||||||
|
|
||||||
|
// now lets attempt a new spend with the new output of the previous transaction
|
||||||
|
val newStateRef = notarisedStxn1.coreTransaction.outRef<DummyContract.SingleOwnerState>(1)
|
||||||
|
val notarisedStxn2 = aliceNode.startFlowAndRunNetwork(SpeedySpendFlow(newStateRef, bobNode.info.singleIdentity())).resultFuture.getOrThrow()
|
||||||
|
|
||||||
|
// the original transaction is now finalised at Bob (despite the original flow not completing) because Bob resolved the
|
||||||
|
// original transaction from Alice in the second transaction (and Alice had already notarised and finalised the original transaction)
|
||||||
|
val (_, txnStatusBobAgain) = bobNode.services.validatedTransactions.getTransactionInternal(notarisedStxn1.id) ?: fail()
|
||||||
|
assertEquals(TransactionStatus.VERIFIED, txnStatusBobAgain)
|
||||||
|
|
||||||
|
val (_, txnStatusAlice2) = aliceNode.services.validatedTransactions.getTransactionInternal(notarisedStxn2.id) ?: fail()
|
||||||
|
assertEquals(TransactionStatus.VERIFIED, txnStatusAlice2)
|
||||||
|
val (_, txnStatusBob2) = bobNode.services.validatedTransactions.getTransactionInternal(notarisedStxn2.id) ?: fail()
|
||||||
|
assertEquals(TransactionStatus.IN_FLIGHT, txnStatusBob2)
|
||||||
|
|
||||||
|
// Validate attempt at flow finalisation by Bob has no effect on outcome.
|
||||||
|
val finaliseStxn1 = bobNode.startFlowAndRunNetwork(FinaliseSpeedySpendFlow(notarisedStxn1.id, notarisedStxn1.sigs)).resultFuture.getOrThrow()
|
||||||
|
val (_, txnStatusBobYetAgain) = bobNode.services.validatedTransactions.getTransactionInternal(finaliseStxn1.id) ?: fail()
|
||||||
|
assertEquals(TransactionStatus.VERIFIED, txnStatusBobYetAgain)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `two phase finality flow keeps un-notarised transaction where initiator fails to send notary signature`() {
|
||||||
|
val bobNode = createBob(platformVersion = PlatformVersionSwitches.TWO_PHASE_FINALITY)
|
||||||
|
|
||||||
|
val ref = aliceNode.startFlowAndRunNetwork(IssueFlow(notary)).resultFuture.getOrThrow()
|
||||||
|
try {
|
||||||
|
aliceNode.startFlowAndRunNetwork(MimicFinalityFailureFlow(ref, bobNode.info.singleIdentity())).resultFuture.getOrThrow()
|
||||||
|
}
|
||||||
|
catch (e: UnexpectedFlowEndException) {
|
||||||
|
val stxId = SecureHash.parse(e.message)
|
||||||
|
val (_, txnStatusBob) = bobNode.services.validatedTransactions.getTransactionInternal(stxId) ?: fail()
|
||||||
|
assertEquals(TransactionStatus.IN_FLIGHT, txnStatusBob)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `two phase finality flow issuance transaction with observers`() {
|
||||||
|
val bobNode = createBob(platformVersion = PlatformVersionSwitches.TWO_PHASE_FINALITY)
|
||||||
|
|
||||||
|
val stx = aliceNode.startFlowAndRunNetwork(CashIssueWithObserversFlow(
|
||||||
|
Amount(1000L, GBP), OpaqueBytes.of(1), notary,
|
||||||
|
observers = setOf(bobNode.info.singleIdentity()))).resultFuture.getOrThrow().stx
|
||||||
|
|
||||||
|
assertThat(aliceNode.services.validatedTransactions.getTransaction(stx.id)).isNotNull
|
||||||
|
assertThat(bobNode.services.validatedTransactions.getTransaction(stx.id)).isNotNull
|
||||||
|
|
||||||
|
val sdrs = getSenderRecoveryData(stx.id, aliceNode.database).apply {
|
||||||
|
assertEquals(1, this.size)
|
||||||
|
assertEquals(StatesToRecord.ONLY_RELEVANT, this[0].senderStatesToRecord)
|
||||||
|
assertEquals(StatesToRecord.ALL_VISIBLE, this[0].receiverStatesToRecord)
|
||||||
|
assertEquals(SecureHash.sha256(BOB_NAME.toString()), this[0].peerPartyId)
|
||||||
|
}
|
||||||
|
val rdr = getReceiverRecoveryData(stx.id, bobNode).apply {
|
||||||
|
assertNotNull(this)
|
||||||
|
val hashedDL = HashedDistributionList.decrypt(this!!.encryptedDistributionList.bytes, aliceNode.internals.encryptionService)
|
||||||
|
assertEquals(StatesToRecord.ONLY_RELEVANT, hashedDL.senderStatesToRecord)
|
||||||
|
assertEquals(SecureHash.sha256(aliceNode.info.singleIdentity().name.toString()), this.peerPartyId)
|
||||||
|
assertEquals(mapOf<SecureHash, StatesToRecord>(SecureHash.sha256(BOB_NAME.toString()) to StatesToRecord.ALL_VISIBLE), hashedDL.peerHashToStatesToRecord)
|
||||||
|
}
|
||||||
|
validateSenderAndReceiverTimestamps(sdrs, rdr!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `two phase finality flow payment transaction with observers`() {
|
||||||
|
val bobNode = createBob(platformVersion = PlatformVersionSwitches.TWO_PHASE_FINALITY)
|
||||||
|
val charlieNode = createNode(CHARLIE_NAME, platformVersion = PlatformVersionSwitches.TWO_PHASE_FINALITY)
|
||||||
|
|
||||||
|
// issue some cash
|
||||||
|
aliceNode.startFlow(CashIssueFlow(Amount(1000L, GBP), OpaqueBytes.of(1), notary)).resultFuture.getOrThrow().stx
|
||||||
|
|
||||||
|
// standard issuance with observers passed in as FinalityFlow sessions
|
||||||
|
val stx = aliceNode.startFlowAndRunNetwork(CashPaymentWithObserversFlow(
|
||||||
|
amount = Amount(100L, GBP),
|
||||||
|
recipient = bobNode.info.singleIdentity(),
|
||||||
|
observers = setOf(charlieNode.info.singleIdentity()))).resultFuture.getOrThrow()
|
||||||
|
|
||||||
|
assertThat(aliceNode.services.validatedTransactions.getTransaction(stx.id)).isNotNull
|
||||||
|
assertThat(bobNode.services.validatedTransactions.getTransaction(stx.id)).isNotNull
|
||||||
|
assertThat(charlieNode.services.validatedTransactions.getTransaction(stx.id)).isNotNull
|
||||||
|
|
||||||
|
val sdrs = getSenderRecoveryData(stx.id, aliceNode.database).apply {
|
||||||
|
assertEquals(2, this.size)
|
||||||
|
assertEquals(StatesToRecord.ONLY_RELEVANT, this[0].senderStatesToRecord)
|
||||||
|
assertEquals(SecureHash.sha256(BOB_NAME.toString()), this[0].peerPartyId)
|
||||||
|
assertEquals(StatesToRecord.ALL_VISIBLE, this[1].receiverStatesToRecord)
|
||||||
|
assertEquals(SecureHash.sha256(CHARLIE_NAME.toString()), this[1].peerPartyId)
|
||||||
|
}
|
||||||
|
val rdr = getReceiverRecoveryData(stx.id, bobNode).apply {
|
||||||
|
assertNotNull(this)
|
||||||
|
val hashedDL = HashedDistributionList.decrypt(this!!.encryptedDistributionList.bytes, aliceNode.internals.encryptionService)
|
||||||
|
assertEquals(StatesToRecord.ONLY_RELEVANT, hashedDL.senderStatesToRecord)
|
||||||
|
assertEquals(SecureHash.sha256(aliceNode.info.singleIdentity().name.toString()), this.peerPartyId)
|
||||||
|
// note: Charlie assertion here is using the hinted StatesToRecord value passed to it from Alice
|
||||||
|
assertEquals(mapOf<SecureHash, StatesToRecord>(
|
||||||
|
SecureHash.sha256(BOB_NAME.toString()) to StatesToRecord.ONLY_RELEVANT,
|
||||||
|
SecureHash.sha256(CHARLIE_NAME.toString()) to StatesToRecord.ALL_VISIBLE
|
||||||
|
), hashedDL.peerHashToStatesToRecord)
|
||||||
|
}
|
||||||
|
validateSenderAndReceiverTimestamps(sdrs, rdr!!)
|
||||||
|
|
||||||
|
// exercise the new FinalityFlow observerSessions constructor parameter
|
||||||
|
val stx3 = aliceNode.startFlowAndRunNetwork(CashPaymentWithObserversFlow(
|
||||||
|
amount = Amount(100L, GBP),
|
||||||
|
recipient = bobNode.info.singleIdentity(),
|
||||||
|
observers = setOf(charlieNode.info.singleIdentity()),
|
||||||
|
useObserverSessions = true)).resultFuture.getOrThrow()
|
||||||
|
|
||||||
|
assertThat(aliceNode.services.validatedTransactions.getTransaction(stx3.id)).isNotNull
|
||||||
|
assertThat(bobNode.services.validatedTransactions.getTransaction(stx3.id)).isNotNull
|
||||||
|
assertThat(charlieNode.services.validatedTransactions.getTransaction(stx3.id)).isNotNull
|
||||||
|
|
||||||
|
val senderDistributionRecords = getSenderRecoveryData(stx3.id, aliceNode.database).apply {
|
||||||
|
assertEquals(2, this.size)
|
||||||
|
assertEquals(this[0].timestamp, this[1].timestamp)
|
||||||
|
}
|
||||||
|
getReceiverRecoveryData(stx3.id, bobNode).apply {
|
||||||
|
assertThat(this).isNotNull
|
||||||
|
assertEquals(senderDistributionRecords[0].timestamp, this!!.timestamp)
|
||||||
|
}
|
||||||
|
getReceiverRecoveryData(stx3.id, charlieNode).apply {
|
||||||
|
assertThat(this).isNotNull
|
||||||
|
assertEquals(senderDistributionRecords[0].timestamp, this!!.timestamp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun validateSenderAndReceiverTimestamps(sdrs: List<SenderDistributionRecord>, rdr: ReceiverDistributionRecord) {
|
||||||
|
sdrs.map {
|
||||||
|
assertEquals(it.timestamp, rdr.timestamp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `two phase finality flow payment transaction using confidential identities`() {
|
||||||
|
val bobNode = createBob(platformVersion = PlatformVersionSwitches.TWO_PHASE_FINALITY)
|
||||||
|
|
||||||
|
aliceNode.startFlow(CashIssueFlow(Amount(1000L, GBP), OpaqueBytes.of(1), notary)).resultFuture.getOrThrow().stx
|
||||||
|
val stx = aliceNode.startFlowAndRunNetwork(CashPaymentFlow(
|
||||||
|
amount = Amount(100L, GBP),
|
||||||
|
recipient = bobNode.info.singleIdentity(),
|
||||||
|
anonymous = true)).resultFuture.getOrThrow().stx
|
||||||
|
|
||||||
|
assertThat(aliceNode.services.validatedTransactions.getTransaction(stx.id)).isNotNull
|
||||||
|
assertThat(bobNode.services.validatedTransactions.getTransaction(stx.id)).isNotNull
|
||||||
|
|
||||||
|
val sdr = getSenderRecoveryData(stx.id, aliceNode.database).apply {
|
||||||
|
assertEquals(1, this.size)
|
||||||
|
assertEquals(StatesToRecord.ONLY_RELEVANT, this[0].senderStatesToRecord)
|
||||||
|
assertEquals(SecureHash.sha256(BOB_NAME.toString()), this[0].peerPartyId)
|
||||||
|
}
|
||||||
|
val rdr = getReceiverRecoveryData(stx.id, bobNode).apply {
|
||||||
|
assertNotNull(this)
|
||||||
|
val hashedDL = HashedDistributionList.decrypt(this!!.encryptedDistributionList.bytes, aliceNode.internals.encryptionService)
|
||||||
|
assertEquals(StatesToRecord.ONLY_RELEVANT, hashedDL.senderStatesToRecord)
|
||||||
|
assertEquals(SecureHash.sha256(aliceNode.info.singleIdentity().name.toString()), this.peerPartyId)
|
||||||
|
assertEquals(mapOf<SecureHash, StatesToRecord>(SecureHash.sha256(BOB_NAME.toString()) to StatesToRecord.ONLY_RELEVANT), hashedDL.peerHashToStatesToRecord)
|
||||||
|
}
|
||||||
|
validateSenderAndReceiverTimestamps(sdr, rdr!!)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getSenderRecoveryData(id: SecureHash, database: CordaPersistence): List<SenderDistributionRecord> {
|
||||||
|
val fromDb = database.transaction {
|
||||||
|
session.createQuery(
|
||||||
|
"from ${DBSenderDistributionRecord::class.java.name} where transaction_id = :transactionId",
|
||||||
|
DBSenderDistributionRecord::class.java
|
||||||
|
).setParameter("transactionId", id.toString()).resultList
|
||||||
|
}
|
||||||
|
return fromDb.map { it.toSenderDistributionRecord() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getReceiverRecoveryData(txId: SecureHash, receiver: TestStartedNode): ReceiverDistributionRecord? {
|
||||||
|
return receiver.database.transaction {
|
||||||
|
session.createQuery(
|
||||||
|
"from ${DBReceiverDistributionRecord::class.java.name} where transaction_id = :transactionId",
|
||||||
|
DBReceiverDistributionRecord::class.java
|
||||||
|
).setParameter("transactionId", txId.toString()).resultList
|
||||||
|
}.singleOrNull()?.toReceiverDistributionRecord()
|
||||||
|
}
|
||||||
|
|
||||||
|
@StartableByRPC
|
||||||
|
class IssueFlow(val notary: Party) : FlowLogic<StateAndRef<DummyContract.SingleOwnerState>>() {
|
||||||
|
|
||||||
|
@Suspendable
|
||||||
|
override fun call(): StateAndRef<DummyContract.SingleOwnerState> {
|
||||||
|
val partyAndReference = PartyAndReference(ourIdentity, OpaqueBytes.of(1))
|
||||||
|
val txBuilder = DummyContract.generateInitial(Random().nextInt(), notary, partyAndReference)
|
||||||
|
val signedTransaction = serviceHub.signInitialTransaction(txBuilder, ourIdentity.owningKey)
|
||||||
|
val notarised = subFlow(FinalityFlow(signedTransaction, emptySet<FlowSession>()))
|
||||||
|
return notarised.coreTransaction.outRef(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@StartableByRPC
|
||||||
|
@InitiatingFlow
|
||||||
|
class SpendFlow(private val stateAndRef: StateAndRef<DummyContract.SingleOwnerState>, private val newOwner: Party,
|
||||||
|
private val handlePropagatedNotaryError: Boolean = false) : FlowLogic<SignedTransaction>() {
|
||||||
|
|
||||||
|
@Suspendable
|
||||||
|
override fun call(): SignedTransaction {
|
||||||
|
val txBuilder = DummyContract.move(stateAndRef, newOwner)
|
||||||
|
val signedTransaction = serviceHub.signInitialTransaction(txBuilder, ourIdentity.owningKey)
|
||||||
|
val sessionWithCounterParty = initiateFlow(newOwner)
|
||||||
|
sessionWithCounterParty.send(handlePropagatedNotaryError)
|
||||||
|
return subFlow(FinalityFlow(signedTransaction, setOf(sessionWithCounterParty)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
@InitiatedBy(SpendFlow::class)
|
||||||
|
class AcceptSpendFlow(private val otherSide: FlowSession) : FlowLogic<Unit>() {
|
||||||
|
|
||||||
|
@Suspendable
|
||||||
|
override fun call() {
|
||||||
|
val handleNotaryError = otherSide.receive<Boolean>().unwrap { it }
|
||||||
|
subFlow(ReceiveFinalityFlow(otherSide, handlePropagatedNotaryError = handleNotaryError))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This flow allows an Initiator to race ahead of a Receiver when using Two Phase Finality.
|
||||||
|
* The initiator transaction will be finalised, so output states can be used in a follow-up transaction.
|
||||||
|
* The receiver transaction will not be finalised, causing ledger inconsistency.
|
||||||
|
*/
|
||||||
|
@StartableByRPC
|
||||||
|
@InitiatingFlow
|
||||||
|
class SpeedySpendFlow(private val stateAndRef: StateAndRef<DummyContract.SingleOwnerState>, private val newOwner: Party) : FlowLogic<SignedTransaction>() {
|
||||||
|
|
||||||
|
@Suspendable
|
||||||
|
override fun call(): SignedTransaction {
|
||||||
|
val newState = StateAndContract(DummyContract.SingleOwnerState(99999, ourIdentity), DummyContract.PROGRAM_ID)
|
||||||
|
val txBuilder = DummyContract.move(stateAndRef, newOwner).withItems(newState)
|
||||||
|
val signedTransaction = serviceHub.signInitialTransaction(txBuilder, ourIdentity.owningKey)
|
||||||
|
val sessionWithCounterParty = initiateFlow(newOwner)
|
||||||
|
try {
|
||||||
|
subFlow(FinalityFlow(signedTransaction, setOf(sessionWithCounterParty)))
|
||||||
|
}
|
||||||
|
catch (e: FinalisationFailedException) {
|
||||||
|
// expected (transaction has been notarised by Initiator)
|
||||||
|
return e.notarisedTxn
|
||||||
|
}
|
||||||
|
return signedTransaction
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
@InitiatedBy(SpeedySpendFlow::class)
|
||||||
|
class AcceptSpeedySpendFlow(private val otherSideSession: FlowSession) : FlowLogic<SignedTransaction>() {
|
||||||
|
|
||||||
|
@Suspendable
|
||||||
|
override fun call(): SignedTransaction {
|
||||||
|
// Mimic ReceiveFinalityFlow but fail to finalise
|
||||||
|
try {
|
||||||
|
val stx = subFlow(ReceiveTransactionFlow(otherSideSession, false, StatesToRecord.ONLY_RELEVANT, true))
|
||||||
|
require(NotarySigCheck.needsNotarySignature(stx))
|
||||||
|
logger.info("Peer recording transaction without notary signature.")
|
||||||
|
(serviceHub as ServiceHubCoreInternal).recordUnnotarisedTransaction(stx)
|
||||||
|
otherSideSession.send(FetchDataFlow.Request.End) // Finish fetching data (overrideAutoAck)
|
||||||
|
logger.info("Peer recorded transaction without notary signature.")
|
||||||
|
|
||||||
|
val notarySignatures = otherSideSession.receive<List<TransactionSignature>>()
|
||||||
|
.unwrap { it }
|
||||||
|
logger.info("Peer received notarised signature.")
|
||||||
|
(serviceHub as ServiceHubCoreInternal).finalizeTransactionWithExtraSignatures(stx + notarySignatures, notarySignatures, StatesToRecord.ONLY_RELEVANT)
|
||||||
|
throw FinalisationFailedException(stx + notarySignatures)
|
||||||
|
}
|
||||||
|
catch (e: SQLException) {
|
||||||
|
logger.error("Peer failure upon recording or finalising transaction: $e")
|
||||||
|
otherSideSession.send(FetchDataFlow.Request.End) // Finish fetching data (overrideAutoAck)
|
||||||
|
throw UnexpectedFlowEndException("Peer failure upon recording or finalising transaction.", e.cause)
|
||||||
|
}
|
||||||
|
catch (uae: TransactionVerificationException.UntrustedAttachmentsException) {
|
||||||
|
logger.error("Peer failure upon receiving transaction: $uae")
|
||||||
|
otherSideSession.send(FetchDataFlow.Request.End) // Finish fetching data (overrideAutoAck)
|
||||||
|
throw uae
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FinaliseSpeedySpendFlow(val id: SecureHash, private val sigs: List<TransactionSignature>) : FlowLogic<SignedTransaction>() {
|
||||||
|
|
||||||
|
@Suspendable
|
||||||
|
override fun call(): SignedTransaction {
|
||||||
|
// Mimic ReceiveFinalityFlow finalisation
|
||||||
|
val stx = serviceHub.validatedTransactions.getTransaction(id) ?: throw FlowException("Missing transaction: $id")
|
||||||
|
(serviceHub as ServiceHubCoreInternal).finalizeTransactionWithExtraSignatures(stx + sigs, sigs, StatesToRecord.ONLY_RELEVANT)
|
||||||
|
logger.info("Peer finalised transaction with notary signature.")
|
||||||
|
|
||||||
|
return stx + sigs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@InitiatingFlow
|
||||||
|
class MimicFinalityFailureFlow(private val stateAndRef: StateAndRef<DummyContract.SingleOwnerState>, private val newOwner: Party) : FlowLogic<SignedTransaction>() {
|
||||||
|
// Mimic FinalityFlow but trigger UnexpectedFlowEndException in ReceiveFinality whilst awaiting receipt of notary signature
|
||||||
|
@Suspendable
|
||||||
|
override fun call(): SignedTransaction {
|
||||||
|
val txBuilder = DummyContract.move(stateAndRef, newOwner)
|
||||||
|
val stxn = serviceHub.signInitialTransaction(txBuilder, ourIdentity.owningKey)
|
||||||
|
val sessionWithCounterParty = initiateFlow(newOwner)
|
||||||
|
subFlow(object : SendTransactionFlow(stxn, setOf(sessionWithCounterParty), emptySet(), StatesToRecord.ONLY_RELEVANT, true) {
|
||||||
|
override fun isFinality(): Boolean = true
|
||||||
|
})
|
||||||
|
throw UnexpectedFlowEndException("${stxn.id}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
@InitiatedBy(MimicFinalityFailureFlow::class)
|
||||||
|
class TriggerReceiveFinalityFlow(private val otherSide: FlowSession) : FlowLogic<Unit>() {
|
||||||
|
@Suspendable
|
||||||
|
override fun call() {
|
||||||
|
subFlow(ReceiveFinalityFlow(otherSide))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FinalisationFailedException(val notarisedTxn: SignedTransaction) : FlowException("Failed to finalise transaction with notary signature.")
|
||||||
|
|
||||||
|
private fun createBob(cordapps: List<TestCordappInternal> = emptyList(), platformVersion: Int = PLATFORM_VERSION): TestStartedNode {
|
||||||
|
return mockNet.createNode(InternalMockNodeParameters(legalName = BOB_NAME, additionalCordapps = cordapps,
|
||||||
|
version = MOCK_VERSION_INFO.copy(platformVersion = platformVersion)))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createNode(legalName: CordaX500Name, cordapps: List<TestCordappInternal> = emptyList(), platformVersion: Int = PLATFORM_VERSION): TestStartedNode {
|
||||||
|
return mockNet.createNode(InternalMockNodeParameters(legalName = legalName, additionalCordapps = cordapps,
|
||||||
|
version = MOCK_VERSION_INFO.copy(platformVersion = platformVersion)))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun TestStartedNode.issuesCashTo(recipient: TestStartedNode): SignedTransaction {
|
private fun TestStartedNode.issuesCashTo(recipient: TestStartedNode): SignedTransaction {
|
||||||
|
@ -15,7 +15,7 @@ class TestNoSecurityDataVendingFlow(otherSideSession: FlowSession) : DataVending
|
|||||||
// Hack to not send the first message.
|
// Hack to not send the first message.
|
||||||
otherSideSession.receive()
|
otherSideSession.receive()
|
||||||
} else {
|
} else {
|
||||||
super.sendPayloadAndReceiveDataRequest(this.otherSideSession, payload)
|
super.sendPayloadAndReceiveDataRequest(this.otherSessions.first(), payload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,7 +4,13 @@ import co.paralleluniverse.fibers.Suspendable
|
|||||||
import com.natpryce.hamkrest.MatchResult
|
import com.natpryce.hamkrest.MatchResult
|
||||||
import com.natpryce.hamkrest.Matcher
|
import com.natpryce.hamkrest.Matcher
|
||||||
import com.natpryce.hamkrest.equalTo
|
import com.natpryce.hamkrest.equalTo
|
||||||
import net.corda.core.flows.*
|
import net.corda.core.flows.FinalityFlow
|
||||||
|
import net.corda.core.flows.FlowLogic
|
||||||
|
import net.corda.core.flows.FlowSession
|
||||||
|
import net.corda.core.flows.InitiatedBy
|
||||||
|
import net.corda.core.flows.InitiatingFlow
|
||||||
|
import net.corda.core.flows.ReceiveFinalityFlow
|
||||||
|
import net.corda.core.flows.StartableByRPC
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.FlowStateMachineHandle
|
import net.corda.core.internal.FlowStateMachineHandle
|
||||||
import net.corda.core.messaging.CordaRPCOps
|
import net.corda.core.messaging.CordaRPCOps
|
||||||
@ -58,4 +64,13 @@ interface WithFinality : WithMockNet {
|
|||||||
subFlow(ReceiveFinalityFlow(otherSide))
|
subFlow(ReceiveFinalityFlow(otherSide))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@StartableByRPC
|
||||||
|
class OldFinalityInvoker(private val transaction: SignedTransaction) : FlowLogic<SignedTransaction>() {
|
||||||
|
@Suspendable
|
||||||
|
override fun call(): SignedTransaction {
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
|
return subFlow(FinalityFlow(transaction))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,12 +99,17 @@ class ResolveTransactionsFlowTest {
|
|||||||
// DOCEND 1
|
// DOCEND 1
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
@Test(timeout=300_000)
|
||||||
fun `dependency with an error`() {
|
fun `dependency with an error fails fast upon prior attempt to record transaction with missing signature`() {
|
||||||
val stx = makeTransactions(signFirstTX = false).second
|
val exception = assertFailsWith(IllegalStateException::class) {
|
||||||
val p = TestFlow(setOf(stx.id), megaCorp)
|
val stx = makeTransactions(signFirstTX = false).second
|
||||||
val future = miniCorpNode.startFlow(p)
|
// fails fast in above operation
|
||||||
mockNet.runNetwork()
|
// prior to platform version 13, same failure would occur upon transaction resolution
|
||||||
assertFailsWith(SignedTransaction.SignaturesMissingException::class) { future.getOrThrow() }
|
val p = TestFlow(setOf(stx.id), megaCorp)
|
||||||
|
val future = miniCorpNode.startFlow(p)
|
||||||
|
mockNet.runNetwork()
|
||||||
|
future.getOrThrow()
|
||||||
|
}
|
||||||
|
assertTrue(exception.cause.toString().contains("SignaturesMissingException"))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout=300_000)
|
@Test(timeout=300_000)
|
||||||
|
@ -30,6 +30,8 @@ import java.time.Duration
|
|||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
import kotlin.test.assertFails
|
import kotlin.test.assertFails
|
||||||
|
import kotlin.test.assertNotEquals
|
||||||
|
import kotlin.test.assertNull
|
||||||
|
|
||||||
class NetworkParametersTest {
|
class NetworkParametersTest {
|
||||||
private val mockNet = InternalMockNetwork(
|
private val mockNet = InternalMockNetwork(
|
||||||
@ -93,6 +95,32 @@ class NetworkParametersTest {
|
|||||||
assertEquals(twoDays, nm2.eventHorizon)
|
assertEquals(twoDays, nm2.eventHorizon)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(timeout=300_000)
|
||||||
|
fun `that transactionRecoveryPeriod and confidentialIdentityPreGenerationPeriod aren't required`() {
|
||||||
|
// this is defensive tests in response to CORDA-2769
|
||||||
|
val aliceNotaryParty = TestIdentity(ALICE_NAME).party
|
||||||
|
val aliceNotaryInfo = NotaryInfo(aliceNotaryParty, false)
|
||||||
|
val nm1 = NetworkParameters(
|
||||||
|
minimumPlatformVersion = 1,
|
||||||
|
notaries = listOf(aliceNotaryInfo),
|
||||||
|
maxMessageSize = Int.MAX_VALUE,
|
||||||
|
maxTransactionSize = Int.MAX_VALUE,
|
||||||
|
modifiedTime = Instant.now(),
|
||||||
|
epoch = 1,
|
||||||
|
whitelistedContractImplementations = mapOf("MyClass" to listOf(AttachmentId.allOnesHash)),
|
||||||
|
eventHorizon = Duration.ofDays(1)
|
||||||
|
)
|
||||||
|
|
||||||
|
assertNull(nm1.recoveryMaximumBackupInterval)
|
||||||
|
assertNull(nm1.confidentialIdentityMinimumBackupInterval)
|
||||||
|
|
||||||
|
val nm2 = nm1.copy(recoveryMaximumBackupInterval = 10.days, confidentialIdentityMinimumBackupInterval = 10.days)
|
||||||
|
|
||||||
|
assertNotEquals(nm1.recoveryMaximumBackupInterval, nm2.recoveryMaximumBackupInterval)
|
||||||
|
assertNotEquals(nm1.confidentialIdentityMinimumBackupInterval, nm2.confidentialIdentityMinimumBackupInterval)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Notaries tests
|
// Notaries tests
|
||||||
@Test(timeout=300_000)
|
@Test(timeout=300_000)
|
||||||
fun `choosing notary not specified in network parameters will fail`() {
|
fun `choosing notary not specified in network parameters will fail`() {
|
||||||
|
@ -80,7 +80,7 @@ class LedgerTransactionQueryTests {
|
|||||||
.addOutputState(dummyState, DummyContract.PROGRAM_ID)
|
.addOutputState(dummyState, DummyContract.PROGRAM_ID)
|
||||||
.addCommand(dummyCommand())
|
.addCommand(dummyCommand())
|
||||||
)
|
)
|
||||||
services.recordTransactions(fakeIssueTx)
|
services.recordTransactions(fakeIssueTx, disableSignatureVerification = true)
|
||||||
val dummyStateRef = StateRef(fakeIssueTx.id, 0)
|
val dummyStateRef = StateRef(fakeIssueTx.id, 0)
|
||||||
return StateAndRef(TransactionState(dummyState, DummyContract.PROGRAM_ID, DUMMY_NOTARY, constraint = AlwaysAcceptAttachmentConstraint), dummyStateRef)
|
return StateAndRef(TransactionState(dummyState, DummyContract.PROGRAM_ID, DUMMY_NOTARY, constraint = AlwaysAcceptAttachmentConstraint), dummyStateRef)
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ apply plugin: 'com.jfrog.artifactory'
|
|||||||
|
|
||||||
description 'Corda core'
|
description 'Corda core'
|
||||||
|
|
||||||
// required by DJVM and Avian JVM (for running inside the SGX enclave) which only supports Java 8.
|
|
||||||
targetCompatibility = VERSION_1_8
|
targetCompatibility = VERSION_1_8
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
@ -73,8 +72,8 @@ dependencies {
|
|||||||
compile "net.i2p.crypto:eddsa:$eddsa_version"
|
compile "net.i2p.crypto:eddsa:$eddsa_version"
|
||||||
|
|
||||||
// Bouncy castle support needed for X509 certificate manipulation
|
// Bouncy castle support needed for X509 certificate manipulation
|
||||||
compile "org.bouncycastle:bcprov-jdk15on:${bouncycastle_version}"
|
compile "org.bouncycastle:bcprov-jdk18on:${bouncycastle_version}"
|
||||||
compile "org.bouncycastle:bcpkix-jdk15on:${bouncycastle_version}"
|
compile "org.bouncycastle:bcpkix-jdk18on:${bouncycastle_version}"
|
||||||
|
|
||||||
// JPA 2.2 annotations.
|
// JPA 2.2 annotations.
|
||||||
compile "javax.persistence:javax.persistence-api:2.2"
|
compile "javax.persistence:javax.persistence-api:2.2"
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package net.corda.core.crypto;
|
package net.corda.core.crypto;
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM;
|
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
@ -29,7 +27,6 @@ import java.util.Arrays;
|
|||||||
* NB: This class originally comes from the Apache licensed bitcoinj library. The original author of this code is the
|
* NB: This class originally comes from the Apache licensed bitcoinj library. The original author of this code is the
|
||||||
* same as the original author of the R3 repository.
|
* same as the original author of the R3 repository.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
public class Base58 {
|
public class Base58 {
|
||||||
private static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray();
|
private static final char[] ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz".toCharArray();
|
||||||
private static final char ENCODED_ZERO = ALPHABET[0];
|
private static final char ENCODED_ZERO = ALPHABET[0];
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
package net.corda.core.flows;
|
package net.corda.core.flows;
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM;
|
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An exception that may be identified with an ID. If an exception originates in a counter-flow this ID will be
|
* An exception that may be identified with an ID. If an exception originates in a counter-flow this ID will be
|
||||||
* propagated. This allows correlation of error conditions across different flows.
|
* propagated. This allows correlation of error conditions across different flows.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
public interface IdentifiableException {
|
public interface IdentifiableException {
|
||||||
/**
|
/**
|
||||||
* @return the ID of the error, or null if the error doesn't have it set (yet).
|
* @return the ID of the error, or null if the error doesn't have it set (yet).
|
||||||
|
@ -6,6 +6,5 @@ import net.corda.core.serialization.CordaSerializable
|
|||||||
* Allows an implementing [Throwable] to be propagated to clients.
|
* Allows an implementing [Throwable] to be propagated to clients.
|
||||||
*/
|
*/
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
@KeepForDJVM
|
|
||||||
@Deprecated("This is no longer used as the exception obfuscation feature is no longer available.")
|
@Deprecated("This is no longer used as the exception obfuscation feature is no longer available.")
|
||||||
interface ClientRelevantError
|
interface ClientRelevantError
|
@ -4,7 +4,6 @@ import net.corda.core.serialization.CordaSerializable
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
@KeepForDJVM
|
|
||||||
interface CordaThrowable {
|
interface CordaThrowable {
|
||||||
var originalExceptionClassName: String?
|
var originalExceptionClassName: String?
|
||||||
val originalMessage: String?
|
val originalMessage: String?
|
||||||
@ -13,7 +12,6 @@ interface CordaThrowable {
|
|||||||
fun addSuppressed(suppressed: Array<Throwable>)
|
fun addSuppressed(suppressed: Array<Throwable>)
|
||||||
}
|
}
|
||||||
|
|
||||||
@KeepForDJVM
|
|
||||||
open class CordaException internal constructor(override var originalExceptionClassName: String? = null,
|
open class CordaException internal constructor(override var originalExceptionClassName: String? = null,
|
||||||
private var _message: String? = null,
|
private var _message: String? = null,
|
||||||
private var _cause: Throwable? = null) : Exception(null, null, true, true), CordaThrowable {
|
private var _cause: Throwable? = null) : Exception(null, null, true, true), CordaThrowable {
|
||||||
@ -61,7 +59,6 @@ open class CordaException internal constructor(override var originalExceptionCla
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@KeepForDJVM
|
|
||||||
open class CordaRuntimeException(override var originalExceptionClassName: String?,
|
open class CordaRuntimeException(override var originalExceptionClassName: String?,
|
||||||
private var _message: String?,
|
private var _message: String?,
|
||||||
private var _cause: Throwable?) : RuntimeException(null, null, true, true), CordaThrowable {
|
private var _cause: Throwable?) : RuntimeException(null, null, true, true), CordaThrowable {
|
||||||
|
@ -6,7 +6,6 @@ import net.corda.core.crypto.internal.AliasPrivateKey
|
|||||||
* OIDs used for the Corda platform. All entries MUST be defined in this file only and they MUST NOT be removed.
|
* OIDs used for the Corda platform. All entries MUST be defined in this file only and they MUST NOT be removed.
|
||||||
* If an OID is incorrectly assigned, it should be marked deprecated and NEVER be reused again.
|
* If an OID is incorrectly assigned, it should be marked deprecated and NEVER be reused again.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
object CordaOID {
|
object CordaOID {
|
||||||
/** Assigned to R3, see http://www.oid-info.com/cgi-bin/display?oid=1.3.6.1.4.1.50530&action=display */
|
/** Assigned to R3, see http://www.oid-info.com/cgi-bin/display?oid=1.3.6.1.4.1.50530&action=display */
|
||||||
const val R3_ROOT = "1.3.6.1.4.1.50530"
|
const val R3_ROOT = "1.3.6.1.4.1.50530"
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
package net.corda.core
|
|
||||||
|
|
||||||
import kotlin.annotation.AnnotationRetention.BINARY
|
|
||||||
import kotlin.annotation.AnnotationTarget.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Declare the annotated element to unsuitable for the deterministic version of Corda.
|
|
||||||
*/
|
|
||||||
// DOCSTART 01
|
|
||||||
@Target(
|
|
||||||
FILE,
|
|
||||||
CLASS,
|
|
||||||
CONSTRUCTOR,
|
|
||||||
FUNCTION,
|
|
||||||
PROPERTY_GETTER,
|
|
||||||
PROPERTY_SETTER,
|
|
||||||
PROPERTY,
|
|
||||||
FIELD,
|
|
||||||
TYPEALIAS
|
|
||||||
)
|
|
||||||
@Retention(BINARY)
|
|
||||||
@CordaInternal
|
|
||||||
annotation class DeleteForDJVM
|
|
||||||
// DOCEND 01
|
|
@ -1,18 +0,0 @@
|
|||||||
package net.corda.core
|
|
||||||
|
|
||||||
import kotlin.annotation.AnnotationRetention.BINARY
|
|
||||||
import kotlin.annotation.AnnotationTarget.CLASS
|
|
||||||
import kotlin.annotation.AnnotationTarget.FILE
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This annotates a class or file that we want to include into the deterministic version of Corda Core.
|
|
||||||
* We don't expect everything within that class/file to be deterministic; those non-deterministic
|
|
||||||
* elements need to be annotated with either [DeleteForDJVM] or [StubOutForDJVM] so that they
|
|
||||||
* can be deleted.
|
|
||||||
*/
|
|
||||||
// DOCSTART 01
|
|
||||||
@Target(FILE, CLASS)
|
|
||||||
@Retention(BINARY)
|
|
||||||
@CordaInternal
|
|
||||||
annotation class KeepForDJVM
|
|
||||||
// DOCEND 01
|
|
@ -1,22 +0,0 @@
|
|||||||
package net.corda.core
|
|
||||||
|
|
||||||
import kotlin.annotation.AnnotationRetention.BINARY
|
|
||||||
import kotlin.annotation.AnnotationTarget.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* We expect that almost every non-deterministic element can have its bytecode
|
|
||||||
* deleted entirely from the deterministic version of Corda. This annotation is
|
|
||||||
* for those (hopefully!) few occasions where the non-deterministic function
|
|
||||||
* cannot be deleted. In these cases, the function will be stubbed out instead.
|
|
||||||
*/
|
|
||||||
// DOCSTART 01
|
|
||||||
@Target(
|
|
||||||
CONSTRUCTOR,
|
|
||||||
FUNCTION,
|
|
||||||
PROPERTY_GETTER,
|
|
||||||
PROPERTY_SETTER
|
|
||||||
)
|
|
||||||
@Retention(BINARY)
|
|
||||||
@CordaInternal
|
|
||||||
annotation class StubOutForDJVM
|
|
||||||
// DOCEND 01
|
|
@ -1,7 +1,5 @@
|
|||||||
package net.corda.core.context
|
package net.corda.core.context
|
||||||
|
|
||||||
import net.corda.core.DeleteForDJVM
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.contracts.ScheduledStateRef
|
import net.corda.core.contracts.ScheduledStateRef
|
||||||
import net.corda.core.identity.CordaX500Name
|
import net.corda.core.identity.CordaX500Name
|
||||||
import net.corda.core.internal.telemetry.SerializedTelemetry
|
import net.corda.core.internal.telemetry.SerializedTelemetry
|
||||||
@ -52,7 +50,6 @@ data class InvocationContext(
|
|||||||
/**
|
/**
|
||||||
* Creates an [InvocationContext] with a [Trace] that defaults to a [java.util.UUID] as value and [java.time.Instant.now] timestamp.
|
* Creates an [InvocationContext] with a [Trace] that defaults to a [java.util.UUID] as value and [java.time.Instant.now] timestamp.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
@ -70,7 +67,6 @@ data class InvocationContext(
|
|||||||
/**
|
/**
|
||||||
* Creates an [InvocationContext] with [InvocationOrigin.RPC] origin.
|
* Creates an [InvocationContext] with [InvocationOrigin.RPC] origin.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
@ -86,28 +82,24 @@ data class InvocationContext(
|
|||||||
/**
|
/**
|
||||||
* Creates an [InvocationContext] with [InvocationOrigin.Peer] origin.
|
* Creates an [InvocationContext] with [InvocationOrigin.Peer] origin.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun peer(party: CordaX500Name, trace: Trace = Trace.newInstance(), externalTrace: Trace? = null, impersonatedActor: Actor? = null): InvocationContext = newInstance(InvocationOrigin.Peer(party), trace, null, externalTrace, impersonatedActor)
|
fun peer(party: CordaX500Name, trace: Trace = Trace.newInstance(), externalTrace: Trace? = null, impersonatedActor: Actor? = null): InvocationContext = newInstance(InvocationOrigin.Peer(party), trace, null, externalTrace, impersonatedActor)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an [InvocationContext] with [InvocationOrigin.Service] origin.
|
* Creates an [InvocationContext] with [InvocationOrigin.Service] origin.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun service(serviceClassName: String, owningLegalIdentity: CordaX500Name, trace: Trace = Trace.newInstance(), externalTrace: Trace? = null): InvocationContext = newInstance(InvocationOrigin.Service(serviceClassName, owningLegalIdentity), trace, null, externalTrace)
|
fun service(serviceClassName: String, owningLegalIdentity: CordaX500Name, trace: Trace = Trace.newInstance(), externalTrace: Trace? = null): InvocationContext = newInstance(InvocationOrigin.Service(serviceClassName, owningLegalIdentity), trace, null, externalTrace)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an [InvocationContext] with [InvocationOrigin.Scheduled] origin.
|
* Creates an [InvocationContext] with [InvocationOrigin.Scheduled] origin.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun scheduled(scheduledState: ScheduledStateRef, trace: Trace = Trace.newInstance(), externalTrace: Trace? = null): InvocationContext = newInstance(InvocationOrigin.Scheduled(scheduledState), trace, null, externalTrace)
|
fun scheduled(scheduledState: ScheduledStateRef, trace: Trace = Trace.newInstance(), externalTrace: Trace? = null): InvocationContext = newInstance(InvocationOrigin.Scheduled(scheduledState), trace, null, externalTrace)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an [InvocationContext] with [InvocationOrigin.Shell] origin.
|
* Creates an [InvocationContext] with [InvocationOrigin.Shell] origin.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun shell(trace: Trace = Trace.newInstance(), externalTrace: Trace? = null): InvocationContext = InvocationContext(InvocationOrigin.Shell, trace, null, externalTrace)
|
fun shell(trace: Trace = Trace.newInstance(), externalTrace: Trace? = null): InvocationContext = InvocationContext(InvocationOrigin.Shell, trace, null, externalTrace)
|
||||||
}
|
}
|
||||||
@ -161,7 +153,6 @@ data class InvocationContext(
|
|||||||
/**
|
/**
|
||||||
* Models an initiator in Corda, can be a user, a service, etc.
|
* Models an initiator in Corda, can be a user, a service, etc.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
data class Actor(val id: Id, val serviceId: AuthServiceId, val owningLegalIdentity: CordaX500Name) {
|
data class Actor(val id: Id, val serviceId: AuthServiceId, val owningLegalIdentity: CordaX500Name) {
|
||||||
|
|
||||||
@ -173,7 +164,6 @@ data class Actor(val id: Id, val serviceId: AuthServiceId, val owningLegalIdenti
|
|||||||
/**
|
/**
|
||||||
* Actor id.
|
* Actor id.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
data class Id(val value: String)
|
data class Id(val value: String)
|
||||||
}
|
}
|
||||||
@ -181,7 +171,6 @@ data class Actor(val id: Id, val serviceId: AuthServiceId, val owningLegalIdenti
|
|||||||
/**
|
/**
|
||||||
* Represents the source of an action such as a flow start, an RPC, a shell command etc.
|
* Represents the source of an action such as a flow start, an RPC, a shell command etc.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
sealed class InvocationOrigin {
|
sealed class InvocationOrigin {
|
||||||
/**
|
/**
|
||||||
@ -230,6 +219,5 @@ sealed class InvocationOrigin {
|
|||||||
/**
|
/**
|
||||||
* Authentication / Authorisation Service ID.
|
* Authentication / Authorisation Service ID.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
data class AuthServiceId(val value: String)
|
data class AuthServiceId(val value: String)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.context
|
package net.corda.core.context
|
||||||
|
|
||||||
import net.corda.core.DeleteForDJVM
|
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.utilities.Id
|
import net.corda.core.utilities.Id
|
||||||
import net.corda.core.utilities.UuidGenerator
|
import net.corda.core.utilities.UuidGenerator
|
||||||
@ -17,7 +16,6 @@ data class Trace(val invocationId: InvocationId, val sessionId: SessionId) {
|
|||||||
/**
|
/**
|
||||||
* Creates a trace using a [InvocationId.newInstance] with default arguments and a [SessionId] matching the value and timestamp from the invocation id..
|
* Creates a trace using a [InvocationId.newInstance] with default arguments and a [SessionId] matching the value and timestamp from the invocation id..
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun newInstance(invocationId: InvocationId = InvocationId.newInstance(), sessionId: SessionId = SessionId(invocationId.value, invocationId.timestamp)) = Trace(invocationId, sessionId)
|
fun newInstance(invocationId: InvocationId = InvocationId.newInstance(), sessionId: SessionId = SessionId(invocationId.value, invocationId.timestamp)) = Trace(invocationId, sessionId)
|
||||||
}
|
}
|
||||||
@ -34,7 +32,6 @@ data class Trace(val invocationId: InvocationId, val sessionId: SessionId) {
|
|||||||
/**
|
/**
|
||||||
* Creates an invocation id using a [java.util.UUID] as value and [Instant.now] as timestamp.
|
* Creates an invocation id using a [java.util.UUID] as value and [Instant.now] as timestamp.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun newInstance(value: String = UuidGenerator.next().toString(), timestamp: Instant = Instant.now()) = InvocationId(value, timestamp)
|
fun newInstance(value: String = UuidGenerator.next().toString(), timestamp: Instant = Instant.now()) = InvocationId(value, timestamp)
|
||||||
}
|
}
|
||||||
@ -52,9 +49,8 @@ data class Trace(val invocationId: InvocationId, val sessionId: SessionId) {
|
|||||||
/**
|
/**
|
||||||
* Creates a session id using a [java.util.UUID] as value and [Instant.now] as timestamp.
|
* Creates a session id using a [java.util.UUID] as value and [Instant.now] as timestamp.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun newInstance(value: String = UuidGenerator.next().toString(), timestamp: Instant = Instant.now()) = SessionId(value, timestamp)
|
fun newInstance(value: String = UuidGenerator.next().toString(), timestamp: Instant = Instant.now()) = SessionId(value, timestamp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.contracts
|
package net.corda.core.contracts
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.crypto.CompositeKey
|
import net.corda.core.crypto.CompositeKey
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
@ -37,7 +36,6 @@ interface TokenizableAssetInfo {
|
|||||||
* @property token the type of token this is an amount of. This is usually a singleton.
|
* @property token the type of token this is an amount of. This is usually a singleton.
|
||||||
* @param T the type of the token, for example [Currency]. T should implement [TokenizableAssetInfo] if automatic conversion to/from a display format is required.
|
* @param T the type of the token, for example [Currency]. T should implement [TokenizableAssetInfo] if automatic conversion to/from a display format is required.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
data class Amount<T : Any>(val quantity: Long, val displayTokenSize: BigDecimal, val token: T) : Comparable<Amount<T>> {
|
data class Amount<T : Any>(val quantity: Long, val displayTokenSize: BigDecimal, val token: T) : Comparable<Amount<T>> {
|
||||||
// TODO Proper lookup of currencies in a locale and context sensitive fashion is not supported and is left to the application.
|
// TODO Proper lookup of currencies in a locale and context sensitive fashion is not supported and is left to the application.
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package net.corda.core.contracts
|
package net.corda.core.contracts
|
||||||
|
|
||||||
import net.corda.core.DoNotImplement
|
import net.corda.core.DoNotImplement
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.extractFile
|
import net.corda.core.internal.extractFile
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
@ -31,7 +30,6 @@ import java.util.jar.JarInputStream
|
|||||||
* Finally, using ZIPs ensures files have a timestamp associated with them, and enables informational attachments
|
* Finally, using ZIPs ensures files have a timestamp associated with them, and enables informational attachments
|
||||||
* to be password protected (although in current releases password protected ZIPs are likely to fail to work).
|
* to be password protected (although in current releases password protected ZIPs are likely to fail to work).
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
@DoNotImplement
|
@DoNotImplement
|
||||||
interface Attachment : NamedByHash {
|
interface Attachment : NamedByHash {
|
||||||
|
@ -2,7 +2,6 @@ package net.corda.core.contracts
|
|||||||
|
|
||||||
import net.corda.core.CordaInternal
|
import net.corda.core.CordaInternal
|
||||||
import net.corda.core.DoNotImplement
|
import net.corda.core.DoNotImplement
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.contracts.AlwaysAcceptAttachmentConstraint.isSatisfiedBy
|
import net.corda.core.contracts.AlwaysAcceptAttachmentConstraint.isSatisfiedBy
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.crypto.isFulfilledBy
|
import net.corda.core.crypto.isFulfilledBy
|
||||||
@ -38,7 +37,6 @@ interface AttachmentConstraint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** An [AttachmentConstraint] where [isSatisfiedBy] always returns true. */
|
/** An [AttachmentConstraint] where [isSatisfiedBy] always returns true. */
|
||||||
@KeepForDJVM
|
|
||||||
object AlwaysAcceptAttachmentConstraint : AttachmentConstraint {
|
object AlwaysAcceptAttachmentConstraint : AttachmentConstraint {
|
||||||
override fun isSatisfiedBy(attachment: Attachment) = true
|
override fun isSatisfiedBy(attachment: Attachment) = true
|
||||||
}
|
}
|
||||||
@ -48,7 +46,6 @@ object AlwaysAcceptAttachmentConstraint : AttachmentConstraint {
|
|||||||
* The state protected by this constraint can only be used in a transaction created with that version of the jar.
|
* The state protected by this constraint can only be used in a transaction created with that version of the jar.
|
||||||
* And a receiving node will only accept it if a cordapp with that hash has (is) been deployed on the node.
|
* And a receiving node will only accept it if a cordapp with that hash has (is) been deployed on the node.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
data class HashAttachmentConstraint(val attachmentId: SecureHash) : AttachmentConstraint {
|
data class HashAttachmentConstraint(val attachmentId: SecureHash) : AttachmentConstraint {
|
||||||
companion object {
|
companion object {
|
||||||
val disableHashConstraints = System.getProperty("net.corda.node.disableHashConstraints")?.toBoolean() ?: false
|
val disableHashConstraints = System.getProperty("net.corda.node.disableHashConstraints")?.toBoolean() ?: false
|
||||||
@ -69,7 +66,6 @@ data class HashAttachmentConstraint(val attachmentId: SecureHash) : AttachmentCo
|
|||||||
* See: [net.corda.core.node.NetworkParameters.whitelistedContractImplementations]
|
* See: [net.corda.core.node.NetworkParameters.whitelistedContractImplementations]
|
||||||
* It allows for centralized control over the cordapps that can be used.
|
* It allows for centralized control over the cordapps that can be used.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
object WhitelistedByZoneAttachmentConstraint : AttachmentConstraint {
|
object WhitelistedByZoneAttachmentConstraint : AttachmentConstraint {
|
||||||
override fun isSatisfiedBy(attachment: Attachment): Boolean {
|
override fun isSatisfiedBy(attachment: Attachment): Boolean {
|
||||||
return if (attachment is AttachmentWithContext) {
|
return if (attachment is AttachmentWithContext) {
|
||||||
@ -83,7 +79,6 @@ object WhitelistedByZoneAttachmentConstraint : AttachmentConstraint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@KeepForDJVM
|
|
||||||
@Deprecated(
|
@Deprecated(
|
||||||
"The name is no longer valid as multiple constraints were added.",
|
"The name is no longer valid as multiple constraints were added.",
|
||||||
replaceWith = ReplaceWith("AutomaticPlaceholderConstraint"),
|
replaceWith = ReplaceWith("AutomaticPlaceholderConstraint"),
|
||||||
@ -102,7 +97,6 @@ object AutomaticHashConstraint : AttachmentConstraint {
|
|||||||
* The resolution occurs in [TransactionBuilder.toWireTransaction] and is based on the input states and the attachments.
|
* The resolution occurs in [TransactionBuilder.toWireTransaction] and is based on the input states and the attachments.
|
||||||
* If the [Contract] was not annotated with [NoConstraintPropagation], then the platform will ensure the correct constraint propagation.
|
* If the [Contract] was not annotated with [NoConstraintPropagation], then the platform will ensure the correct constraint propagation.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
object AutomaticPlaceholderConstraint : AttachmentConstraint {
|
object AutomaticPlaceholderConstraint : AttachmentConstraint {
|
||||||
override fun isSatisfiedBy(attachment: Attachment): Boolean {
|
override fun isSatisfiedBy(attachment: Attachment): Boolean {
|
||||||
throw UnsupportedOperationException("Contracts cannot be satisfied by an AutomaticPlaceholderConstraint placeholder.")
|
throw UnsupportedOperationException("Contracts cannot be satisfied by an AutomaticPlaceholderConstraint placeholder.")
|
||||||
@ -115,7 +109,6 @@ object AutomaticPlaceholderConstraint : AttachmentConstraint {
|
|||||||
*
|
*
|
||||||
* @property key A [PublicKey] that must be fulfilled by the owning keys of the attachment's signing parties.
|
* @property key A [PublicKey] that must be fulfilled by the owning keys of the attachment's signing parties.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
data class SignatureAttachmentConstraint(val key: PublicKey) : AttachmentConstraint {
|
data class SignatureAttachmentConstraint(val key: PublicKey) : AttachmentConstraint {
|
||||||
override fun isSatisfiedBy(attachment: Attachment): Boolean {
|
override fun isSatisfiedBy(attachment: Attachment): Boolean {
|
||||||
log.debug("Checking signature constraints: verifying $key in contract attachment signer keys: ${attachment.signerKeys}")
|
log.debug("Checking signature constraints: verifying $key in contract attachment signer keys: ${attachment.signerKeys}")
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package net.corda.core.contracts
|
package net.corda.core.contracts
|
||||||
|
|
||||||
import net.corda.core.CordaInternal
|
import net.corda.core.CordaInternal
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.internal.cordapp.CordappImpl.Companion.DEFAULT_CORDAPP_VERSION
|
import net.corda.core.internal.cordapp.CordappImpl.Companion.DEFAULT_CORDAPP_VERSION
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
|
|
||||||
@ -12,7 +11,6 @@ import java.security.PublicKey
|
|||||||
* @property contract The contract name contained within the JAR. A Contract attachment has to contain at least 1 contract.
|
* @property contract The contract name contained within the JAR. A Contract attachment has to contain at least 1 contract.
|
||||||
* @property additionalContracts Additional contract names contained within the JAR.
|
* @property additionalContracts Additional contract names contained within the JAR.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class ContractAttachment private constructor(
|
class ContractAttachment private constructor(
|
||||||
val attachment: Attachment,
|
val attachment: Attachment,
|
||||||
val contract: ContractClassName,
|
val contract: ContractClassName,
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.contracts
|
package net.corda.core.contracts
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
|
|
||||||
@ -12,7 +11,6 @@ import net.corda.core.serialization.CordaSerializable
|
|||||||
* notary is responsible for ensuring there is no "double spending" by only signing a transaction if the input states
|
* notary is responsible for ensuring there is no "double spending" by only signing a transaction if the input states
|
||||||
* are all free.
|
* are all free.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
interface ContractState {
|
interface ContractState {
|
||||||
/**
|
/**
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
@file:JvmName("ContractsDSL")
|
@file:JvmName("ContractsDSL")
|
||||||
@file:KeepForDJVM
|
|
||||||
package net.corda.core.contracts
|
package net.corda.core.contracts
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.uncheckedCast
|
import net.corda.core.internal.uncheckedCast
|
||||||
@ -18,7 +16,6 @@ import java.util.*
|
|||||||
|
|
||||||
//// Requirements /////////////////////////////////////////////////////////////////////////////////////////////////////
|
//// Requirements /////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@KeepForDJVM
|
|
||||||
object Requirements {
|
object Requirements {
|
||||||
/** Throws [IllegalArgumentException] if the given expression evaluates to false. */
|
/** Throws [IllegalArgumentException] if the given expression evaluates to false. */
|
||||||
@Suppress("NOTHING_TO_INLINE") // Inlining this takes it out of our committed ABI.
|
@Suppress("NOTHING_TO_INLINE") // Inlining this takes it out of our committed ABI.
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.contracts
|
package net.corda.core.contracts
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.flows.FlowException
|
import net.corda.core.flows.FlowException
|
||||||
import net.corda.core.identity.AbstractParty
|
import net.corda.core.identity.AbstractParty
|
||||||
import net.corda.core.serialization.SerializableCalculatedProperty
|
import net.corda.core.serialization.SerializableCalculatedProperty
|
||||||
@ -27,7 +26,6 @@ class InsufficientBalanceException(val amountMissing: Amount<*>) : FlowException
|
|||||||
* @param T a type that represents the asset in question. This should describe the basic type of the asset
|
* @param T a type that represents the asset in question. This should describe the basic type of the asset
|
||||||
* (GBP, USD, oil, shares in company <X>, etc.) and any additional metadata (issuer, grade, class, etc.).
|
* (GBP, USD, oil, shares in company <X>, etc.) and any additional metadata (issuer, grade, class, etc.).
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
interface FungibleAsset<T : Any> : FungibleState<Issued<T>>, OwnableState {
|
interface FungibleAsset<T : Any> : FungibleState<Issued<T>>, OwnableState {
|
||||||
/**
|
/**
|
||||||
* Amount represents a positive quantity of some issued product which can be cash, tokens, assets, or generally
|
* Amount represents a positive quantity of some issued product which can be cash, tokens, assets, or generally
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package net.corda.core.contracts
|
package net.corda.core.contracts
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface to represent things which are fungible, this means that there is an expectation that these things can
|
* Interface to represent things which are fungible, this means that there is an expectation that these things can
|
||||||
* be split and merged. That's the only assumption made by this interface.
|
* be split and merged. That's the only assumption made by this interface.
|
||||||
@ -25,7 +23,6 @@ import net.corda.core.KeepForDJVM
|
|||||||
* [TokenizableAssetInfo].
|
* [TokenizableAssetInfo].
|
||||||
*/
|
*/
|
||||||
// DOCSTART 1
|
// DOCSTART 1
|
||||||
@KeepForDJVM
|
|
||||||
interface FungibleState<T : Any> : ContractState {
|
interface FungibleState<T : Any> : ContractState {
|
||||||
/**
|
/**
|
||||||
* Amount represents a positive quantity of some token which can be cash, tokens, stock, agreements, or generally
|
* Amount represents a positive quantity of some token which can be cash, tokens, stock, agreements, or generally
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package net.corda.core.contracts
|
package net.corda.core.contracts
|
||||||
|
|
||||||
import net.corda.core.DeleteForDJVM
|
|
||||||
import net.corda.core.DoNotImplement
|
import net.corda.core.DoNotImplement
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.node.ServiceHub
|
import net.corda.core.node.ServiceHub
|
||||||
import net.corda.core.node.services.Vault
|
import net.corda.core.node.services.Vault
|
||||||
import net.corda.core.node.services.queryBy
|
import net.corda.core.node.services.queryBy
|
||||||
@ -18,7 +16,6 @@ import net.corda.core.transactions.LedgerTransaction
|
|||||||
* [StaticPointer]s are for use with any type of [ContractState].
|
* [StaticPointer]s are for use with any type of [ContractState].
|
||||||
*/
|
*/
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
@KeepForDJVM
|
|
||||||
@DoNotImplement
|
@DoNotImplement
|
||||||
sealed class StatePointer<T : ContractState> {
|
sealed class StatePointer<T : ContractState> {
|
||||||
|
|
||||||
@ -70,7 +67,6 @@ sealed class StatePointer<T : ContractState> {
|
|||||||
*
|
*
|
||||||
* @param services a [ServiceHub] implementation is required to resolve the pointer.
|
* @param services a [ServiceHub] implementation is required to resolve the pointer.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
abstract fun resolve(services: ServiceHub): StateAndRef<T>
|
abstract fun resolve(services: ServiceHub): StateAndRef<T>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -89,7 +85,6 @@ sealed class StatePointer<T : ContractState> {
|
|||||||
* - The [ContractState] may not be known by the node performing the look-up in which case the [resolve] method will
|
* - The [ContractState] may not be known by the node performing the look-up in which case the [resolve] method will
|
||||||
* throw a [TransactionResolutionException]
|
* throw a [TransactionResolutionException]
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class StaticPointer<T : ContractState>(
|
class StaticPointer<T : ContractState>(
|
||||||
override val pointer: StateRef,
|
override val pointer: StateRef,
|
||||||
override val type: Class<T>,
|
override val type: Class<T>,
|
||||||
@ -110,7 +105,6 @@ class StaticPointer<T : ContractState>(
|
|||||||
*/
|
*/
|
||||||
@Throws(TransactionResolutionException::class)
|
@Throws(TransactionResolutionException::class)
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@DeleteForDJVM
|
|
||||||
override fun resolve(services: ServiceHub): StateAndRef<T> {
|
override fun resolve(services: ServiceHub): StateAndRef<T> {
|
||||||
val transactionState = services.loadState(pointer) as TransactionState<T>
|
val transactionState = services.loadState(pointer) as TransactionState<T>
|
||||||
val castState: T = type.cast(transactionState.data)
|
val castState: T = type.cast(transactionState.data)
|
||||||
@ -148,7 +142,6 @@ class StaticPointer<T : ContractState>(
|
|||||||
* then the transaction with such a reference state cannot be committed to the ledger until the most up-to-date version
|
* then the transaction with such a reference state cannot be committed to the ledger until the most up-to-date version
|
||||||
* of the [LinearState] is available. See reference states documentation on docs.corda.net for more info.
|
* of the [LinearState] is available. See reference states documentation on docs.corda.net for more info.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class LinearPointer<T : LinearState>(
|
class LinearPointer<T : LinearState>(
|
||||||
override val pointer: UniqueIdentifier,
|
override val pointer: UniqueIdentifier,
|
||||||
override val type: Class<T>,
|
override val type: Class<T>,
|
||||||
@ -171,7 +164,6 @@ class LinearPointer<T : LinearState>(
|
|||||||
* @param services a [ServiceHub] implementation is required to perform a vault query.
|
* @param services a [ServiceHub] implementation is required to perform a vault query.
|
||||||
*/
|
*/
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@DeleteForDJVM
|
|
||||||
override fun resolve(services: ServiceHub): StateAndRef<T> {
|
override fun resolve(services: ServiceHub): StateAndRef<T> {
|
||||||
// Return the latest version of the linear state.
|
// Return the latest version of the linear state.
|
||||||
// This query will only ever return one or zero states.
|
// This query will only ever return one or zero states.
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
@file:JvmName("Structures")
|
@file:JvmName("Structures")
|
||||||
@file:KeepForDJVM
|
|
||||||
package net.corda.core.contracts
|
package net.corda.core.contracts
|
||||||
|
|
||||||
import net.corda.core.DeleteForDJVM
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.crypto.secureRandomBytes
|
import net.corda.core.crypto.secureRandomBytes
|
||||||
import net.corda.core.crypto.toStringShort
|
import net.corda.core.crypto.toStringShort
|
||||||
@ -45,7 +42,6 @@ interface NamedByHash {
|
|||||||
* of product may differentiate different kinds of asset within the same logical class e.g the currency, or
|
* of product may differentiate different kinds of asset within the same logical class e.g the currency, or
|
||||||
* it may just be a type marker for a single custom asset.
|
* it may just be a type marker for a single custom asset.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
data class Issued<out P : Any>(val issuer: PartyAndReference, val product: P) {
|
data class Issued<out P : Any>(val issuer: PartyAndReference, val product: P) {
|
||||||
init {
|
init {
|
||||||
@ -72,13 +68,11 @@ fun <T : Any> Amount<Issued<T>>.withoutIssuer(): Amount<T> = Amount(quantity, di
|
|||||||
/**
|
/**
|
||||||
* Return structure for [OwnableState.withNewOwner]
|
* Return structure for [OwnableState.withNewOwner]
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
data class CommandAndState(val command: CommandData, val ownableState: OwnableState)
|
data class CommandAndState(val command: CommandData, val ownableState: OwnableState)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A contract state that can have a single owner.
|
* A contract state that can have a single owner.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
interface OwnableState : ContractState {
|
interface OwnableState : ContractState {
|
||||||
/** There must be a MoveCommand signed by this key to claim the amount. */
|
/** There must be a MoveCommand signed by this key to claim the amount. */
|
||||||
val owner: AbstractParty
|
val owner: AbstractParty
|
||||||
@ -89,7 +83,6 @@ interface OwnableState : ContractState {
|
|||||||
// DOCEND 3
|
// DOCEND 3
|
||||||
|
|
||||||
/** Something which is scheduled to happen at a point in time. */
|
/** Something which is scheduled to happen at a point in time. */
|
||||||
@KeepForDJVM
|
|
||||||
interface Scheduled {
|
interface Scheduled {
|
||||||
val scheduledAt: Instant
|
val scheduledAt: Instant
|
||||||
}
|
}
|
||||||
@ -102,7 +95,6 @@ interface Scheduled {
|
|||||||
* lifecycle processing needs to take place. e.g. a fixing or a late payment etc.
|
* lifecycle processing needs to take place. e.g. a fixing or a late payment etc.
|
||||||
*/
|
*/
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
@KeepForDJVM
|
|
||||||
data class ScheduledStateRef(val ref: StateRef, override val scheduledAt: Instant) : Scheduled
|
data class ScheduledStateRef(val ref: StateRef, override val scheduledAt: Instant) : Scheduled
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -117,7 +109,6 @@ data class ScheduledStateRef(val ref: StateRef, override val scheduledAt: Instan
|
|||||||
* for a particular [ContractState] have been processed/fired etc. If the activity is not "on ledger" then the
|
* for a particular [ContractState] have been processed/fired etc. If the activity is not "on ledger" then the
|
||||||
* scheduled activity shouldn't be either.
|
* scheduled activity shouldn't be either.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
data class ScheduledActivity(val logicRef: FlowLogicRef, override val scheduledAt: Instant) : Scheduled
|
data class ScheduledActivity(val logicRef: FlowLogicRef, override val scheduledAt: Instant) : Scheduled
|
||||||
|
|
||||||
// DOCSTART 2
|
// DOCSTART 2
|
||||||
@ -126,7 +117,6 @@ data class ScheduledActivity(val logicRef: FlowLogicRef, override val scheduledA
|
|||||||
*
|
*
|
||||||
* This simplifies the job of tracking the current version of certain types of state in e.g. a vault.
|
* This simplifies the job of tracking the current version of certain types of state in e.g. a vault.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
interface LinearState : ContractState {
|
interface LinearState : ContractState {
|
||||||
/**
|
/**
|
||||||
* Unique id shared by all LinearState states throughout history within the vaults of all parties.
|
* Unique id shared by all LinearState states throughout history within the vaults of all parties.
|
||||||
@ -136,7 +126,6 @@ interface LinearState : ContractState {
|
|||||||
val linearId: UniqueIdentifier
|
val linearId: UniqueIdentifier
|
||||||
}
|
}
|
||||||
// DOCEND 2
|
// DOCEND 2
|
||||||
@KeepForDJVM
|
|
||||||
interface SchedulableState : ContractState {
|
interface SchedulableState : ContractState {
|
||||||
/**
|
/**
|
||||||
* Indicate whether there is some activity to be performed at some future point in time with respect to this
|
* Indicate whether there is some activity to be performed at some future point in time with respect to this
|
||||||
@ -160,7 +149,6 @@ fun ContractState.hash(algorithm: String): SecureHash = SecureHash.hashAs(algori
|
|||||||
* A stateref is a pointer (reference) to a state, this is an equivalent of an "outpoint" in Bitcoin. It records which
|
* A stateref is a pointer (reference) to a state, this is an equivalent of an "outpoint" in Bitcoin. It records which
|
||||||
* transaction defined the state and where in that transaction it was.
|
* transaction defined the state and where in that transaction it was.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
// DOCSTART 8
|
// DOCSTART 8
|
||||||
data class StateRef(val txhash: SecureHash, val index: Int) {
|
data class StateRef(val txhash: SecureHash, val index: Int) {
|
||||||
@ -169,7 +157,6 @@ data class StateRef(val txhash: SecureHash, val index: Int) {
|
|||||||
// DOCEND 8
|
// DOCEND 8
|
||||||
|
|
||||||
/** A StateAndRef is simply a (state, ref) pair. For instance, a vault (which holds available assets) contains these. */
|
/** A StateAndRef is simply a (state, ref) pair. For instance, a vault (which holds available assets) contains these. */
|
||||||
@KeepForDJVM
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
// DOCSTART 7
|
// DOCSTART 7
|
||||||
data class StateAndRef<out T : ContractState>(val state: TransactionState<T>, val ref: StateRef) {
|
data class StateAndRef<out T : ContractState>(val state: TransactionState<T>, val ref: StateRef) {
|
||||||
@ -179,7 +166,6 @@ data class StateAndRef<out T : ContractState>(val state: TransactionState<T>, va
|
|||||||
// DOCEND 7
|
// DOCEND 7
|
||||||
|
|
||||||
/** A wrapper for a [StateAndRef] indicating that it should be added to a transaction as a reference input state. */
|
/** A wrapper for a [StateAndRef] indicating that it should be added to a transaction as a reference input state. */
|
||||||
@KeepForDJVM
|
|
||||||
data class ReferencedStateAndRef<out T : ContractState>(val stateAndRef: StateAndRef<T>)
|
data class ReferencedStateAndRef<out T : ContractState>(val stateAndRef: StateAndRef<T>)
|
||||||
|
|
||||||
/** Filters a list of [StateAndRef] objects according to the type of the states */
|
/** Filters a list of [StateAndRef] objects according to the type of the states */
|
||||||
@ -191,7 +177,6 @@ inline fun <reified T : ContractState> Iterable<StateAndRef<ContractState>>.filt
|
|||||||
* Reference to something being stored or issued by a party e.g. in a vault or (more likely) on their normal
|
* Reference to something being stored or issued by a party e.g. in a vault or (more likely) on their normal
|
||||||
* ledger. The reference is intended to be encrypted so it's meaningless to anyone other than the party.
|
* ledger. The reference is intended to be encrypted so it's meaningless to anyone other than the party.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
data class PartyAndReference(val party: AbstractParty, val reference: OpaqueBytes) {
|
data class PartyAndReference(val party: AbstractParty, val reference: OpaqueBytes) {
|
||||||
override fun toString() = "$party$reference"
|
override fun toString() = "$party$reference"
|
||||||
@ -202,14 +187,12 @@ data class PartyAndReference(val party: AbstractParty, val reference: OpaqueByte
|
|||||||
interface CommandData
|
interface CommandData
|
||||||
|
|
||||||
/** Commands that inherit from this are intended to have no data items: it's only their presence that matters. */
|
/** Commands that inherit from this are intended to have no data items: it's only their presence that matters. */
|
||||||
@KeepForDJVM
|
|
||||||
abstract class TypeOnlyCommandData : CommandData {
|
abstract class TypeOnlyCommandData : CommandData {
|
||||||
override fun equals(other: Any?) = other?.javaClass == javaClass
|
override fun equals(other: Any?) = other?.javaClass == javaClass
|
||||||
override fun hashCode() = javaClass.name.hashCode()
|
override fun hashCode() = javaClass.name.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Command data/content plus pubkey pair: the signature is stored at the end of the serialized bytes */
|
/** Command data/content plus pubkey pair: the signature is stored at the end of the serialized bytes */
|
||||||
@KeepForDJVM
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
data class Command<T : CommandData>(val value: T, val signers: List<PublicKey>) {
|
data class Command<T : CommandData>(val value: T, val signers: List<PublicKey>) {
|
||||||
// TODO Introduce NonEmptyList?
|
// TODO Introduce NonEmptyList?
|
||||||
@ -224,7 +207,6 @@ data class Command<T : CommandData>(val value: T, val signers: List<PublicKey>)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A common move command for contract states which can change owner. */
|
/** A common move command for contract states which can change owner. */
|
||||||
@KeepForDJVM
|
|
||||||
interface MoveCommand : CommandData {
|
interface MoveCommand : CommandData {
|
||||||
/**
|
/**
|
||||||
* Contract code the moved state(s) are for the attention of, for example to indicate that the states are moved in
|
* Contract code the moved state(s) are for the attention of, for example to indicate that the states are moved in
|
||||||
@ -236,7 +218,6 @@ interface MoveCommand : CommandData {
|
|||||||
|
|
||||||
// DOCSTART 6
|
// DOCSTART 6
|
||||||
/** A [Command] where the signing parties have been looked up if they have a well known/recognised institutional key. */
|
/** A [Command] where the signing parties have been looked up if they have a well known/recognised institutional key. */
|
||||||
@KeepForDJVM
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
data class CommandWithParties<out T : CommandData>(
|
data class CommandWithParties<out T : CommandData>(
|
||||||
val signers: List<PublicKey>,
|
val signers: List<PublicKey>,
|
||||||
@ -256,7 +237,6 @@ data class CommandWithParties<out T : CommandData>(
|
|||||||
*
|
*
|
||||||
* TODO: Contract serialization is likely to change, so the annotation is likely temporary.
|
* TODO: Contract serialization is likely to change, so the annotation is likely temporary.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
interface Contract {
|
interface Contract {
|
||||||
/**
|
/**
|
||||||
@ -288,7 +268,6 @@ annotation class LegalProseReference(val uri: String)
|
|||||||
* more than one state).
|
* more than one state).
|
||||||
* @param NewState the upgraded contract state.
|
* @param NewState the upgraded contract state.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
interface UpgradedContract<in OldState : ContractState, out NewState : ContractState> : Contract {
|
interface UpgradedContract<in OldState : ContractState, out NewState : ContractState> : Contract {
|
||||||
/**
|
/**
|
||||||
* Name of the contract this is an upgraded version of, used as part of verification of upgrade transactions.
|
* Name of the contract this is an upgraded version of, used as part of verification of upgrade transactions.
|
||||||
@ -307,7 +286,6 @@ interface UpgradedContract<in OldState : ContractState, out NewState : ContractS
|
|||||||
* This interface allows specifying a custom legacy contract constraint for upgraded contracts. The default for [UpgradedContract]
|
* This interface allows specifying a custom legacy contract constraint for upgraded contracts. The default for [UpgradedContract]
|
||||||
* is [WhitelistedByZoneAttachmentConstraint].
|
* is [WhitelistedByZoneAttachmentConstraint].
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
interface UpgradedContractWithLegacyConstraint<in OldState : ContractState, out NewState : ContractState> : UpgradedContract<OldState, NewState> {
|
interface UpgradedContractWithLegacyConstraint<in OldState : ContractState, out NewState : ContractState> : UpgradedContract<OldState, NewState> {
|
||||||
/**
|
/**
|
||||||
* A validator for the legacy (pre-upgrade) contract attachments on the transaction.
|
* A validator for the legacy (pre-upgrade) contract attachments on the transaction.
|
||||||
@ -325,14 +303,11 @@ interface UpgradedContractWithLegacyConstraint<in OldState : ContractState, out
|
|||||||
* but it is highlighted that one should always ensure it has sufficient entropy.
|
* but it is highlighted that one should always ensure it has sufficient entropy.
|
||||||
*/
|
*/
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
@KeepForDJVM
|
|
||||||
class PrivacySalt(bytes: ByteArray) : OpaqueBytes(bytes) {
|
class PrivacySalt(bytes: ByteArray) : OpaqueBytes(bytes) {
|
||||||
/** Constructs a salt with a randomly-generated saltLength byte value. */
|
/** Constructs a salt with a randomly-generated saltLength byte value. */
|
||||||
@DeleteForDJVM
|
|
||||||
constructor(saltLength: Int) : this(secureRandomBytes(saltLength))
|
constructor(saltLength: Int) : this(secureRandomBytes(saltLength))
|
||||||
|
|
||||||
/** Constructs a salt with a randomly-generated 32 byte value. */
|
/** Constructs a salt with a randomly-generated 32 byte value. */
|
||||||
@DeleteForDJVM
|
|
||||||
constructor() : this(MINIMUM_SIZE)
|
constructor() : this(MINIMUM_SIZE)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -343,7 +318,6 @@ class PrivacySalt(bytes: ByteArray) : OpaqueBytes(bytes) {
|
|||||||
companion object {
|
companion object {
|
||||||
private const val MINIMUM_SIZE = 32
|
private const val MINIMUM_SIZE = 32
|
||||||
|
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun createFor(algorithm: String): PrivacySalt {
|
fun createFor(algorithm: String): PrivacySalt {
|
||||||
return PrivacySalt(SecureHash.digestLengthFor(algorithm))
|
return PrivacySalt(SecureHash.digestLengthFor(algorithm))
|
||||||
@ -357,5 +331,4 @@ class PrivacySalt(bytes: ByteArray) : OpaqueBytes(bytes) {
|
|||||||
* @property state A state
|
* @property state A state
|
||||||
* @property contract The contract that should verify the state
|
* @property contract The contract that should verify the state
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
data class StateAndContract(val state: ContractState, val contract: ContractClassName)
|
data class StateAndContract(val state: ContractState, val contract: ContractClassName)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.contracts
|
package net.corda.core.contracts
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.internal.div
|
import net.corda.core.internal.div
|
||||||
import net.corda.core.internal.until
|
import net.corda.core.internal.until
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
@ -79,7 +78,6 @@ abstract class TimeWindow {
|
|||||||
/** Returns true iff the given [instant] is within the time interval of this [TimeWindow]. */
|
/** Returns true iff the given [instant] is within the time interval of this [TimeWindow]. */
|
||||||
abstract operator fun contains(instant: Instant): Boolean
|
abstract operator fun contains(instant: Instant): Boolean
|
||||||
|
|
||||||
@KeepForDJVM
|
|
||||||
private data class From(override val fromTime: Instant) : TimeWindow() {
|
private data class From(override val fromTime: Instant) : TimeWindow() {
|
||||||
override val untilTime: Instant? get() = null
|
override val untilTime: Instant? get() = null
|
||||||
override val midpoint: Instant? get() = null
|
override val midpoint: Instant? get() = null
|
||||||
@ -87,7 +85,6 @@ abstract class TimeWindow {
|
|||||||
override fun toString(): String = "[$fromTime, ∞)"
|
override fun toString(): String = "[$fromTime, ∞)"
|
||||||
}
|
}
|
||||||
|
|
||||||
@KeepForDJVM
|
|
||||||
private data class Until(override val untilTime: Instant) : TimeWindow() {
|
private data class Until(override val untilTime: Instant) : TimeWindow() {
|
||||||
override val fromTime: Instant? get() = null
|
override val fromTime: Instant? get() = null
|
||||||
override val midpoint: Instant? get() = null
|
override val midpoint: Instant? get() = null
|
||||||
@ -95,7 +92,6 @@ abstract class TimeWindow {
|
|||||||
override fun toString(): String = "(∞, $untilTime)"
|
override fun toString(): String = "(∞, $untilTime)"
|
||||||
}
|
}
|
||||||
|
|
||||||
@KeepForDJVM
|
|
||||||
private data class Between(override val fromTime: Instant, override val untilTime: Instant) : TimeWindow() {
|
private data class Between(override val fromTime: Instant, override val untilTime: Instant) : TimeWindow() {
|
||||||
init {
|
init {
|
||||||
require(fromTime < untilTime) { "fromTime must be earlier than untilTime" }
|
require(fromTime < untilTime) { "fromTime must be earlier than untilTime" }
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
@file:KeepForDJVM
|
|
||||||
package net.corda.core.contracts
|
package net.corda.core.contracts
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
import net.corda.core.internal.requiredContractClassName
|
import net.corda.core.internal.requiredContractClassName
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package net.corda.core.contracts
|
package net.corda.core.contracts
|
||||||
|
|
||||||
import net.corda.core.CordaException
|
import net.corda.core.CordaException
|
||||||
import net.corda.core.DeleteForDJVM
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import net.corda.core.flows.FlowException
|
import net.corda.core.flows.FlowException
|
||||||
import net.corda.core.identity.Party
|
import net.corda.core.identity.Party
|
||||||
@ -18,7 +16,6 @@ import java.security.PublicKey
|
|||||||
*
|
*
|
||||||
* @property hash Merkle root of the transaction being resolved, see [net.corda.core.transactions.WireTransaction.id]
|
* @property hash Merkle root of the transaction being resolved, see [net.corda.core.transactions.WireTransaction.id]
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
open class TransactionResolutionException @JvmOverloads constructor(val hash: SecureHash, message: String = "Transaction resolution failure for $hash") : FlowException(message) {
|
open class TransactionResolutionException @JvmOverloads constructor(val hash: SecureHash, message: String = "Transaction resolution failure for $hash") : FlowException(message) {
|
||||||
/**
|
/**
|
||||||
* Thrown if a transaction specifies a set of parameters that aren't stored locally yet verification is requested.
|
* Thrown if a transaction specifies a set of parameters that aren't stored locally yet verification is requested.
|
||||||
@ -35,7 +32,6 @@ open class TransactionResolutionException @JvmOverloads constructor(val hash: Se
|
|||||||
*
|
*
|
||||||
* @property hash Hash of the bytes of the attachment, see [Attachment.id]
|
* @property hash Hash of the bytes of the attachment, see [Attachment.id]
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class AttachmentResolutionException(val hash: AttachmentId) : FlowException("Attachment resolution failure for $hash")
|
class AttachmentResolutionException(val hash: AttachmentId) : FlowException("Attachment resolution failure for $hash")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,7 +39,6 @@ class AttachmentResolutionException(val hash: AttachmentId) : FlowException("Att
|
|||||||
* for this error is provided via the [message] and [cause].
|
* for this error is provided via the [message] and [cause].
|
||||||
* @property attachmentId
|
* @property attachmentId
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class BrokenAttachmentException(val attachmentId: AttachmentId, message: String?, cause: Throwable?)
|
class BrokenAttachmentException(val attachmentId: AttachmentId, message: String?, cause: Throwable?)
|
||||||
: FlowException("Attachment $attachmentId has error (${message ?: "no message"})", cause)
|
: FlowException("Attachment $attachmentId has error (${message ?: "no message"})", cause)
|
||||||
|
|
||||||
@ -64,7 +59,6 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
*
|
*
|
||||||
* @property contractClass The fully qualified class name of the failing contract.
|
* @property contractClass The fully qualified class name of the failing contract.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class ContractRejection internal constructor(txId: SecureHash, val contractClass: String, cause: Throwable?, message: String) : TransactionVerificationException(txId, "Contract verification failed: $message, contract: $contractClass", cause) {
|
class ContractRejection internal constructor(txId: SecureHash, val contractClass: String, cause: Throwable?, message: String) : TransactionVerificationException(txId, "Contract verification failed: $message, contract: $contractClass", cause) {
|
||||||
internal constructor(txId: SecureHash, contract: Contract, cause: Throwable) : this(txId, contract.javaClass.name, cause, cause.message ?: "")
|
internal constructor(txId: SecureHash, contract: Contract, cause: Throwable) : this(txId, contract.javaClass.name, cause, cause.message ?: "")
|
||||||
}
|
}
|
||||||
@ -78,7 +72,6 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
* @property inputConstraint The constraint of the input state.
|
* @property inputConstraint The constraint of the input state.
|
||||||
* @property outputConstraint The constraint of the outputs state.
|
* @property outputConstraint The constraint of the outputs state.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class ConstraintPropagationRejection(txId: SecureHash, message: String) : TransactionVerificationException(txId, message, null) {
|
class ConstraintPropagationRejection(txId: SecureHash, message: String) : TransactionVerificationException(txId, message, null) {
|
||||||
constructor(txId: SecureHash,
|
constructor(txId: SecureHash,
|
||||||
contractClass: String,
|
contractClass: String,
|
||||||
@ -97,7 +90,6 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
*
|
*
|
||||||
* @property contractClass The fully qualified class name of the failing contract.
|
* @property contractClass The fully qualified class name of the failing contract.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class ContractConstraintRejection(txId: SecureHash, val contractClass: String)
|
class ContractConstraintRejection(txId: SecureHash, val contractClass: String)
|
||||||
: TransactionVerificationException(txId, "Contract constraints failed for $contractClass", null)
|
: TransactionVerificationException(txId, "Contract constraints failed for $contractClass", null)
|
||||||
|
|
||||||
@ -107,7 +99,6 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
* @property contractClass The fully qualified class name of the failing contract.
|
* @property contractClass The fully qualified class name of the failing contract.
|
||||||
* @property reason a message containing the reason the constraint is invalid included in thrown the exception.
|
* @property reason a message containing the reason the constraint is invalid included in thrown the exception.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class InvalidConstraintRejection(txId: SecureHash, val contractClass: String, val reason: String)
|
class InvalidConstraintRejection(txId: SecureHash, val contractClass: String, val reason: String)
|
||||||
: TransactionVerificationException(txId, "Contract constraints failed for $contractClass. $reason", null)
|
: TransactionVerificationException(txId, "Contract constraints failed for $contractClass. $reason", null)
|
||||||
|
|
||||||
@ -117,7 +108,6 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
*
|
*
|
||||||
* @property contractClass The fully qualified class name of the failing contract.
|
* @property contractClass The fully qualified class name of the failing contract.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class MissingAttachmentRejection(txId: SecureHash, val contractClass: String)
|
class MissingAttachmentRejection(txId: SecureHash, val contractClass: String)
|
||||||
: TransactionVerificationException(txId, "Contract constraints failed, could not find attachment for: $contractClass", null)
|
: TransactionVerificationException(txId, "Contract constraints failed, could not find attachment for: $contractClass", null)
|
||||||
|
|
||||||
@ -130,14 +120,12 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
*
|
*
|
||||||
* @property contractClass The fully qualified class name of the failing contract.
|
* @property contractClass The fully qualified class name of the failing contract.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class ConflictingAttachmentsRejection(txId: SecureHash, val contractClass: String)
|
class ConflictingAttachmentsRejection(txId: SecureHash, val contractClass: String)
|
||||||
: TransactionVerificationException(txId, "Contract constraints failed for: $contractClass, because multiple attachments providing this contract were attached.", null)
|
: TransactionVerificationException(txId, "Contract constraints failed for: $contractClass, because multiple attachments providing this contract were attached.", null)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates that the same attachment has been added multiple times to a transaction.
|
* Indicates that the same attachment has been added multiple times to a transaction.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class DuplicateAttachmentsRejection(txId: SecureHash, val attachmentId: Attachment)
|
class DuplicateAttachmentsRejection(txId: SecureHash, val attachmentId: Attachment)
|
||||||
: TransactionVerificationException(txId, "The attachment: $attachmentId was added multiple times.", null)
|
: TransactionVerificationException(txId, "The attachment: $attachmentId was added multiple times.", null)
|
||||||
|
|
||||||
@ -147,7 +135,6 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
*
|
*
|
||||||
* @property contractClass The fully qualified class name of the failing contract.
|
* @property contractClass The fully qualified class name of the failing contract.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class ContractCreationError internal constructor(txId: SecureHash, val contractClass: String, cause: Throwable?, message: String)
|
class ContractCreationError internal constructor(txId: SecureHash, val contractClass: String, cause: Throwable?, message: String)
|
||||||
: TransactionVerificationException(txId, "Contract verification failed: $message, could not create contract class: $contractClass", cause) {
|
: TransactionVerificationException(txId, "Contract verification failed: $message, could not create contract class: $contractClass", cause) {
|
||||||
internal constructor(txId: SecureHash, contractClass: String, cause: Throwable) : this(txId, contractClass, cause, cause.message ?: "")
|
internal constructor(txId: SecureHash, contractClass: String, cause: Throwable) : this(txId, contractClass, cause, cause.message ?: "")
|
||||||
@ -159,7 +146,6 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
* @property txNotary the [Party] specified by the transaction header.
|
* @property txNotary the [Party] specified by the transaction header.
|
||||||
* @property outputNotary the [Party] specified by the errant state.
|
* @property outputNotary the [Party] specified by the errant state.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class NotaryChangeInWrongTransactionType(txId: SecureHash, val txNotary: Party, val outputNotary: Party)
|
class NotaryChangeInWrongTransactionType(txId: SecureHash, val txNotary: Party, val outputNotary: Party)
|
||||||
: TransactionVerificationException(txId, "Found unexpected notary change in transaction. Tx notary: $txNotary, found: $outputNotary", null)
|
: TransactionVerificationException(txId, "Found unexpected notary change in transaction. Tx notary: $txNotary, found: $outputNotary", null)
|
||||||
|
|
||||||
@ -172,7 +158,6 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
* @property missing the index of the state missing the encumbrance.
|
* @property missing the index of the state missing the encumbrance.
|
||||||
* @property inOut whether the issue exists in the input list or output list.
|
* @property inOut whether the issue exists in the input list or output list.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class TransactionMissingEncumbranceException(txId: SecureHash, val missing: Int, val inOut: Direction)
|
class TransactionMissingEncumbranceException(txId: SecureHash, val missing: Int, val inOut: Direction)
|
||||||
: TransactionVerificationException(txId, "Missing required encumbrance $missing in $inOut", null)
|
: TransactionVerificationException(txId, "Missing required encumbrance $missing in $inOut", null)
|
||||||
|
|
||||||
@ -180,7 +165,6 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
* If two or more states refer to another state (as their encumbrance), then the bi-directionality property cannot
|
* If two or more states refer to another state (as their encumbrance), then the bi-directionality property cannot
|
||||||
* be satisfied.
|
* be satisfied.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class TransactionDuplicateEncumbranceException(txId: SecureHash, message: String)
|
class TransactionDuplicateEncumbranceException(txId: SecureHash, message: String)
|
||||||
: TransactionVerificationException(txId, message, null) {
|
: TransactionVerificationException(txId, message, null) {
|
||||||
constructor(txId: SecureHash, index: Int) : this(txId, "The bi-directionality property of encumbered output states " +
|
constructor(txId: SecureHash, index: Int) : this(txId, "The bi-directionality property of encumbered output states " +
|
||||||
@ -191,7 +175,6 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
* An encumbered state should also be referenced as the encumbrance of another state in order to satisfy the
|
* An encumbered state should also be referenced as the encumbrance of another state in order to satisfy the
|
||||||
* bi-directionality property (a full cycle should be present).
|
* bi-directionality property (a full cycle should be present).
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class TransactionNonMatchingEncumbranceException(txId: SecureHash, message: String)
|
class TransactionNonMatchingEncumbranceException(txId: SecureHash, message: String)
|
||||||
: TransactionVerificationException(txId, message, null) {
|
: TransactionVerificationException(txId, message, null) {
|
||||||
constructor(txId: SecureHash, nonMatching: Collection<Int>) : this(txId,
|
constructor(txId: SecureHash, nonMatching: Collection<Int>) : this(txId,
|
||||||
@ -205,7 +188,6 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
* transactions are not supported and thus two encumbered states with different notaries cannot be consumed
|
* transactions are not supported and thus two encumbered states with different notaries cannot be consumed
|
||||||
* in the same transaction.
|
* in the same transaction.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class TransactionNotaryMismatchEncumbranceException(txId: SecureHash, message: String)
|
class TransactionNotaryMismatchEncumbranceException(txId: SecureHash, message: String)
|
||||||
: TransactionVerificationException(txId, message, null) {
|
: TransactionVerificationException(txId, message, null) {
|
||||||
constructor(txId: SecureHash, encumberedIndex: Int, encumbranceIndex: Int, encumberedNotary: Party, encumbranceNotary: Party) :
|
constructor(txId: SecureHash, encumberedIndex: Int, encumbranceIndex: Int, encumberedNotary: Party, encumbranceNotary: Party) :
|
||||||
@ -222,7 +204,6 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
* @param state The [TransactionState] whose bundled state and contract are in conflict.
|
* @param state The [TransactionState] whose bundled state and contract are in conflict.
|
||||||
* @param requiredContractClassName The class name of the contract to which the state belongs.
|
* @param requiredContractClassName The class name of the contract to which the state belongs.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class TransactionContractConflictException(txId: SecureHash, message: String)
|
class TransactionContractConflictException(txId: SecureHash, message: String)
|
||||||
: TransactionVerificationException(txId, message, null) {
|
: TransactionVerificationException(txId, message, null) {
|
||||||
constructor(txId: SecureHash, state: TransactionState<ContractState>, requiredContractClassName: String): this(txId,
|
constructor(txId: SecureHash, state: TransactionState<ContractState>, requiredContractClassName: String): this(txId,
|
||||||
@ -233,7 +214,6 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add reference to documentation
|
// TODO: add reference to documentation
|
||||||
@KeepForDJVM
|
|
||||||
class TransactionRequiredContractUnspecifiedException(txId: SecureHash, message: String)
|
class TransactionRequiredContractUnspecifiedException(txId: SecureHash, message: String)
|
||||||
: TransactionVerificationException(txId, message, null) {
|
: TransactionVerificationException(txId, message, null) {
|
||||||
constructor(txId: SecureHash, state: TransactionState<ContractState>) : this(txId,
|
constructor(txId: SecureHash, state: TransactionState<ContractState>) : this(txId,
|
||||||
@ -247,7 +227,6 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
/**
|
/**
|
||||||
* If the network parameters associated with an input or reference state in a transaction are more recent than the network parameters of the new transaction itself.
|
* If the network parameters associated with an input or reference state in a transaction are more recent than the network parameters of the new transaction itself.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class TransactionNetworkParameterOrderingException(txId: SecureHash, message: String) :
|
class TransactionNetworkParameterOrderingException(txId: SecureHash, message: String) :
|
||||||
TransactionVerificationException(txId, message, null) {
|
TransactionVerificationException(txId, message, null) {
|
||||||
constructor(txId: SecureHash,
|
constructor(txId: SecureHash,
|
||||||
@ -265,7 +244,6 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
* @param txId Id of the transaction that has missing parameters hash in the resolution chain
|
* @param txId Id of the transaction that has missing parameters hash in the resolution chain
|
||||||
* @param missingNetworkParametersHash Missing hash of the network parameters associated to this transaction
|
* @param missingNetworkParametersHash Missing hash of the network parameters associated to this transaction
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class MissingNetworkParametersException(txId: SecureHash, message: String)
|
class MissingNetworkParametersException(txId: SecureHash, message: String)
|
||||||
: TransactionVerificationException(txId, message, null) {
|
: TransactionVerificationException(txId, message, null) {
|
||||||
constructor(txId: SecureHash, missingNetworkParametersHash: SecureHash) :
|
constructor(txId: SecureHash, missingNetworkParametersHash: SecureHash) :
|
||||||
@ -275,13 +253,11 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
/**
|
/**
|
||||||
* @param txId Id of the transaction that Corda is no longer able to verify.
|
* @param txId Id of the transaction that Corda is no longer able to verify.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class BrokenTransactionException(txId: SecureHash, message: String)
|
class BrokenTransactionException(txId: SecureHash, message: String)
|
||||||
: TransactionVerificationException(txId, message, null)
|
: TransactionVerificationException(txId, message, null)
|
||||||
|
|
||||||
/** Whether the inputs or outputs list contains an encumbrance issue, see [TransactionMissingEncumbranceException]. */
|
/** Whether the inputs or outputs list contains an encumbrance issue, see [TransactionMissingEncumbranceException]. */
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
@KeepForDJVM
|
|
||||||
enum class Direction {
|
enum class Direction {
|
||||||
/** Issue in the inputs list. */
|
/** Issue in the inputs list. */
|
||||||
INPUT,
|
INPUT,
|
||||||
@ -294,30 +270,25 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
// as a cause.
|
// as a cause.
|
||||||
/** @suppress This class is not used: duplicate inputs throw a [IllegalStateException] instead. */
|
/** @suppress This class is not used: duplicate inputs throw a [IllegalStateException] instead. */
|
||||||
@Deprecated("This class is not used: duplicate inputs throw a [IllegalStateException] instead.")
|
@Deprecated("This class is not used: duplicate inputs throw a [IllegalStateException] instead.")
|
||||||
@DeleteForDJVM
|
|
||||||
class DuplicateInputStates(txId: SecureHash, val duplicates: NonEmptySet<StateRef>)
|
class DuplicateInputStates(txId: SecureHash, val duplicates: NonEmptySet<StateRef>)
|
||||||
: TransactionVerificationException(txId, "Duplicate inputs: ${duplicates.joinToString()}", null)
|
: TransactionVerificationException(txId, "Duplicate inputs: ${duplicates.joinToString()}", null)
|
||||||
|
|
||||||
/** @suppress This class is obsolete and nothing has ever used it. */
|
/** @suppress This class is obsolete and nothing has ever used it. */
|
||||||
@Deprecated("This class is obsolete and nothing has ever used it.")
|
@Deprecated("This class is obsolete and nothing has ever used it.")
|
||||||
@DeleteForDJVM
|
|
||||||
class MoreThanOneNotary(txId: SecureHash) : TransactionVerificationException(txId, "More than one notary", null)
|
class MoreThanOneNotary(txId: SecureHash) : TransactionVerificationException(txId, "More than one notary", null)
|
||||||
|
|
||||||
/** @suppress This class is obsolete and nothing has ever used it. */
|
/** @suppress This class is obsolete and nothing has ever used it. */
|
||||||
@Deprecated("This class is obsolete and nothing has ever used it.")
|
@Deprecated("This class is obsolete and nothing has ever used it.")
|
||||||
@DeleteForDJVM
|
|
||||||
class SignersMissing(txId: SecureHash, val missing: List<PublicKey>) : TransactionVerificationException(txId, "Signers missing: ${missing.joinToString()}", null)
|
class SignersMissing(txId: SecureHash, val missing: List<PublicKey>) : TransactionVerificationException(txId, "Signers missing: ${missing.joinToString()}", null)
|
||||||
|
|
||||||
/** @suppress This class is obsolete and nothing has ever used it. */
|
/** @suppress This class is obsolete and nothing has ever used it. */
|
||||||
@Deprecated("This class is obsolete and nothing has ever used it.")
|
@Deprecated("This class is obsolete and nothing has ever used it.")
|
||||||
@DeleteForDJVM
|
|
||||||
class InvalidNotaryChange(txId: SecureHash)
|
class InvalidNotaryChange(txId: SecureHash)
|
||||||
: TransactionVerificationException(txId, "Detected a notary change. Outputs must use the same notary as inputs", null)
|
: TransactionVerificationException(txId, "Detected a notary change. Outputs must use the same notary as inputs", null)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrown when multiple attachments provide the same file when building the AttachmentsClassloader for a transaction.
|
* Thrown when multiple attachments provide the same file when building the AttachmentsClassloader for a transaction.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class OverlappingAttachmentsException(txId: SecureHash, val path: String) : TransactionVerificationException(txId, "Multiple attachments define a file at $path.", null)
|
class OverlappingAttachmentsException(txId: SecureHash, val path: String) : TransactionVerificationException(txId, "Multiple attachments define a file at $path.", null)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -336,16 +307,12 @@ abstract class TransactionVerificationException(val txId: SecureHash, message: S
|
|||||||
|
|
||||||
// TODO: Make this descend from TransactionVerificationException so that untrusted attachments cause flows to be hospitalized.
|
// TODO: Make this descend from TransactionVerificationException so that untrusted attachments cause flows to be hospitalized.
|
||||||
/** Thrown during classloading upon encountering an untrusted attachment (eg. not in the [TRUSTED_UPLOADERS] list) */
|
/** Thrown during classloading upon encountering an untrusted attachment (eg. not in the [TRUSTED_UPLOADERS] list) */
|
||||||
@KeepForDJVM
|
|
||||||
class UntrustedAttachmentsException(val txId: SecureHash, val ids: List<SecureHash>) :
|
class UntrustedAttachmentsException(val txId: SecureHash, val ids: List<SecureHash>) :
|
||||||
CordaException("Attempting to load untrusted transaction attachments: $ids. " +
|
CordaException("Attempting to load untrusted transaction attachments: $ids. " +
|
||||||
"At this time these are not loadable because the DJVM sandbox has not yet been integrated. " +
|
|
||||||
"You will need to manually install the CorDapp to whitelist it for use.")
|
"You will need to manually install the CorDapp to whitelist it for use.")
|
||||||
|
|
||||||
@KeepForDJVM
|
|
||||||
class UnsupportedHashTypeException(txId: SecureHash) : TransactionVerificationException(txId, "The transaction Id is defined by an unsupported hash type", null)
|
class UnsupportedHashTypeException(txId: SecureHash) : TransactionVerificationException(txId, "The transaction Id is defined by an unsupported hash type", null)
|
||||||
|
|
||||||
@KeepForDJVM
|
|
||||||
class AttachmentTooBigException(txId: SecureHash) : TransactionVerificationException(
|
class AttachmentTooBigException(txId: SecureHash) : TransactionVerificationException(
|
||||||
txId, "The transaction attachments are too large and exceed both max transaction size and the maximum allowed compression ratio", null)
|
txId, "The transaction attachments are too large and exceed both max transaction size and the maximum allowed compression ratio", null)
|
||||||
|
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package net.corda.core.contracts
|
package net.corda.core.contracts
|
||||||
|
|
||||||
import net.corda.core.DeleteForDJVM
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.internal.VisibleForTesting
|
import net.corda.core.internal.VisibleForTesting
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@ -19,8 +17,7 @@ import java.util.*
|
|||||||
* Subsequent copies and evolutions of a state should just copy the [externalId] and [id] fields unmodified.
|
* Subsequent copies and evolutions of a state should just copy the [externalId] and [id] fields unmodified.
|
||||||
*/
|
*/
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
@KeepForDJVM
|
data class UniqueIdentifier @JvmOverloads constructor(val externalId: String? = null, val id: UUID = UUID.randomUUID()) : Comparable<UniqueIdentifier> {
|
||||||
data class UniqueIdentifier @JvmOverloads @DeleteForDJVM constructor(val externalId: String? = null, val id: UUID = UUID.randomUUID()) : Comparable<UniqueIdentifier> {
|
|
||||||
override fun toString(): String = if (externalId != null) "${externalId}_$id" else id.toString()
|
override fun toString(): String = if (externalId != null) "${externalId}_$id" else id.toString()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.cordapp
|
package net.corda.core.cordapp
|
||||||
|
|
||||||
import net.corda.core.DeleteForDJVM
|
|
||||||
import net.corda.core.DoNotImplement
|
import net.corda.core.DoNotImplement
|
||||||
import net.corda.core.cordapp.Cordapp.Info.*
|
import net.corda.core.cordapp.Cordapp.Info.*
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
@ -41,7 +40,6 @@ import java.net.URL
|
|||||||
* @property targetPlatformVersion The target platform version this CorDapp was designed and tested on.
|
* @property targetPlatformVersion The target platform version this CorDapp was designed and tested on.
|
||||||
*/
|
*/
|
||||||
@DoNotImplement
|
@DoNotImplement
|
||||||
@DeleteForDJVM
|
|
||||||
interface Cordapp {
|
interface Cordapp {
|
||||||
val name: String
|
val name: String
|
||||||
val contractClassNames: List<String>
|
val contractClassNames: List<String>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package net.corda.core.cordapp
|
package net.corda.core.cordapp
|
||||||
|
|
||||||
import net.corda.core.CordaInternal
|
import net.corda.core.CordaInternal
|
||||||
import net.corda.core.DeleteForDJVM
|
|
||||||
import net.corda.core.crypto.SecureHash
|
import net.corda.core.crypto.SecureHash
|
||||||
import java.lang.UnsupportedOperationException
|
import java.lang.UnsupportedOperationException
|
||||||
|
|
||||||
@ -18,7 +17,6 @@ import java.lang.UnsupportedOperationException
|
|||||||
* @property classLoader the classloader used to load this cordapp's classes
|
* @property classLoader the classloader used to load this cordapp's classes
|
||||||
* @property config Configuration for this CorDapp
|
* @property config Configuration for this CorDapp
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
class CordappContext private constructor(
|
class CordappContext private constructor(
|
||||||
val cordapp: Cordapp,
|
val cordapp: Cordapp,
|
||||||
val attachmentId: SecureHash?,
|
val attachmentId: SecureHash?,
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.cordapp
|
package net.corda.core.cordapp
|
||||||
|
|
||||||
import net.corda.core.DeleteForDJVM
|
|
||||||
import net.corda.core.DoNotImplement
|
import net.corda.core.DoNotImplement
|
||||||
import net.corda.core.contracts.ContractClassName
|
import net.corda.core.contracts.ContractClassName
|
||||||
import net.corda.core.node.services.AttachmentId
|
import net.corda.core.node.services.AttachmentId
|
||||||
@ -9,7 +8,6 @@ import net.corda.core.node.services.AttachmentId
|
|||||||
* Provides access to what the node knows about loaded applications.
|
* Provides access to what the node knows about loaded applications.
|
||||||
*/
|
*/
|
||||||
@DoNotImplement
|
@DoNotImplement
|
||||||
@DeleteForDJVM
|
|
||||||
interface CordappProvider {
|
interface CordappProvider {
|
||||||
/**
|
/**
|
||||||
* Exposes the current CorDapp context which will contain information and configuration of the CorDapp that
|
* Exposes the current CorDapp context which will contain information and configuration of the CorDapp that
|
||||||
|
@ -1,10 +1,16 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.utilities.exactAdd
|
import net.corda.core.utilities.exactAdd
|
||||||
import net.corda.core.utilities.sequence
|
import net.corda.core.utilities.sequence
|
||||||
import org.bouncycastle.asn1.*
|
import org.bouncycastle.asn1.ASN1EncodableVector
|
||||||
|
import org.bouncycastle.asn1.ASN1Encoding
|
||||||
|
import org.bouncycastle.asn1.ASN1Integer
|
||||||
|
import org.bouncycastle.asn1.ASN1Object
|
||||||
|
import org.bouncycastle.asn1.ASN1Primitive
|
||||||
|
import org.bouncycastle.asn1.ASN1Sequence
|
||||||
|
import org.bouncycastle.asn1.DERBitString
|
||||||
|
import org.bouncycastle.asn1.DERSequence
|
||||||
import org.bouncycastle.asn1.x509.AlgorithmIdentifier
|
import org.bouncycastle.asn1.x509.AlgorithmIdentifier
|
||||||
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
|
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
@ -27,7 +33,6 @@ import java.util.*
|
|||||||
* @property threshold specifies the minimum total weight required (in the simple case – the minimum number of child
|
* @property threshold specifies the minimum total weight required (in the simple case – the minimum number of child
|
||||||
* signatures required) to satisfy the sub-tree rooted at this node.
|
* signatures required) to satisfy the sub-tree rooted at this node.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class CompositeKey private constructor(val threshold: Int, children: List<NodeAndWeight>) : PublicKey {
|
class CompositeKey private constructor(val threshold: Int, children: List<NodeAndWeight>) : PublicKey {
|
||||||
companion object {
|
companion object {
|
||||||
const val KEY_ALGORITHM = "COMPOSITE"
|
const val KEY_ALGORITHM = "COMPOSITE"
|
||||||
@ -144,7 +149,6 @@ class CompositeKey private constructor(val threshold: Int, children: List<NodeAn
|
|||||||
* Holds node - weight pairs for a CompositeKey. Ordered first by weight, then by node's hashCode.
|
* Holds node - weight pairs for a CompositeKey. Ordered first by weight, then by node's hashCode.
|
||||||
* Each node should be assigned with a positive weight to avoid certain types of weight underflow attacks.
|
* Each node should be assigned with a positive weight to avoid certain types of weight underflow attacks.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
data class NodeAndWeight(val node: PublicKey, val weight: Int) : Comparable<NodeAndWeight>, ASN1Object() {
|
data class NodeAndWeight(val node: PublicKey, val weight: Int) : Comparable<NodeAndWeight>, ASN1Object() {
|
||||||
init {
|
init {
|
||||||
@ -162,7 +166,7 @@ class CompositeKey private constructor(val threshold: Int, children: List<NodeAn
|
|||||||
|
|
||||||
override fun toASN1Primitive(): ASN1Primitive {
|
override fun toASN1Primitive(): ASN1Primitive {
|
||||||
val vector = ASN1EncodableVector()
|
val vector = ASN1EncodableVector()
|
||||||
vector.add(DERBitString(node.encoded))
|
vector.add(DERBitString(Crypto.encodePublicKey(node)))
|
||||||
vector.add(ASN1Integer(weight.toLong()))
|
vector.add(ASN1Integer(weight.toLong()))
|
||||||
return DERSequence(vector)
|
return DERSequence(vector)
|
||||||
}
|
}
|
||||||
@ -243,7 +247,6 @@ class CompositeKey private constructor(val threshold: Int, children: List<NodeAn
|
|||||||
override fun toString() = "(${children.joinToString()})"
|
override fun toString() = "(${children.joinToString()})"
|
||||||
|
|
||||||
/** A helper class for building a [CompositeKey]. */
|
/** A helper class for building a [CompositeKey]. */
|
||||||
@KeepForDJVM
|
|
||||||
class Builder {
|
class Builder {
|
||||||
private val children: MutableList<NodeAndWeight> = mutableListOf()
|
private val children: MutableList<NodeAndWeight> = mutableListOf()
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import java.security.*
|
import java.security.*
|
||||||
import java.security.spec.InvalidKeySpecException
|
import java.security.spec.InvalidKeySpecException
|
||||||
import java.security.spec.KeySpec
|
import java.security.spec.KeySpec
|
||||||
@ -9,7 +8,6 @@ import java.security.spec.X509EncodedKeySpec
|
|||||||
/**
|
/**
|
||||||
* Factory for generating composite keys from ASN.1 format key specifications. This is used by [CordaSecurityProvider].
|
* Factory for generating composite keys from ASN.1 format key specifications. This is used by [CordaSecurityProvider].
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class CompositeKeyFactory : KeyFactorySpi() {
|
class CompositeKeyFactory : KeyFactorySpi() {
|
||||||
|
|
||||||
@Throws(InvalidKeySpecException::class)
|
@Throws(InvalidKeySpecException::class)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.serialization.deserialize
|
import net.corda.core.serialization.deserialize
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.security.InvalidAlgorithmParameterException
|
import java.security.InvalidAlgorithmParameterException
|
||||||
@ -15,7 +14,6 @@ import java.security.spec.AlgorithmParameterSpec
|
|||||||
/**
|
/**
|
||||||
* Dedicated class for storing a set of signatures that comprise [CompositeKey].
|
* Dedicated class for storing a set of signatures that comprise [CompositeKey].
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
class CompositeSignature : Signature(SIGNATURE_ALGORITHM) {
|
class CompositeSignature : Signature(SIGNATURE_ALGORITHM) {
|
||||||
companion object {
|
companion object {
|
||||||
const val SIGNATURE_ALGORITHM = "COMPOSITESIG"
|
const val SIGNATURE_ALGORITHM = "COMPOSITESIG"
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -8,7 +7,6 @@ import net.corda.core.serialization.CordaSerializable
|
|||||||
* serialization format.
|
* serialization format.
|
||||||
*/
|
*/
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
@KeepForDJVM
|
|
||||||
data class CompositeSignaturesWithKeys(val sigs: List<TransactionSignature>) {
|
data class CompositeSignaturesWithKeys(val sigs: List<TransactionSignature>) {
|
||||||
companion object {
|
companion object {
|
||||||
val EMPTY = CompositeSignaturesWithKeys(emptyList())
|
val EMPTY = CompositeSignaturesWithKeys(emptyList())
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.StubOutForDJVM
|
|
||||||
import net.corda.core.crypto.CordaObjectIdentifier.COMPOSITE_KEY
|
import net.corda.core.crypto.CordaObjectIdentifier.COMPOSITE_KEY
|
||||||
import net.corda.core.crypto.CordaObjectIdentifier.COMPOSITE_SIGNATURE
|
import net.corda.core.crypto.CordaObjectIdentifier.COMPOSITE_SIGNATURE
|
||||||
import net.corda.core.crypto.internal.PlatformSecureRandomService
|
import net.corda.core.crypto.internal.PlatformSecureRandomService
|
||||||
@ -10,13 +8,14 @@ import java.security.Provider
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
@KeepForDJVM
|
|
||||||
@Suppress("DEPRECATION") // JDK11: should replace with Provider(String name, double version, String info) (since 9)
|
@Suppress("DEPRECATION") // JDK11: should replace with Provider(String name, double version, String info) (since 9)
|
||||||
class CordaSecurityProvider : Provider(PROVIDER_NAME, 0.1, "$PROVIDER_NAME security provider wrapper") {
|
class CordaSecurityProvider : Provider(PROVIDER_NAME, 0.1, "$PROVIDER_NAME security provider wrapper") {
|
||||||
companion object {
|
companion object {
|
||||||
const val PROVIDER_NAME = "Corda"
|
const val PROVIDER_NAME = "Corda"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val services = ConcurrentHashMap<Pair<String, String>, Optional<Service>>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
put("KeyFactory.${CompositeKey.KEY_ALGORITHM}", CompositeKeyFactory::class.java.name)
|
put("KeyFactory.${CompositeKey.KEY_ALGORITHM}", CompositeKeyFactory::class.java.name)
|
||||||
put("Alg.Alias.KeyFactory.$COMPOSITE_KEY", CompositeKey.KEY_ALGORITHM)
|
put("Alg.Alias.KeyFactory.$COMPOSITE_KEY", CompositeKey.KEY_ALGORITHM)
|
||||||
@ -27,47 +26,19 @@ class CordaSecurityProvider : Provider(PROVIDER_NAME, 0.1, "$PROVIDER_NAME secur
|
|||||||
putPlatformSecureRandomService()
|
putPlatformSecureRandomService()
|
||||||
}
|
}
|
||||||
|
|
||||||
@StubOutForDJVM
|
|
||||||
private fun putPlatformSecureRandomService() {
|
private fun putPlatformSecureRandomService() {
|
||||||
putService(PlatformSecureRandomService(this))
|
putService(PlatformSecureRandomService(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getService(type: String, algorithm: String): Service? = serviceFactory(type, algorithm)
|
override fun getService(type: String, algorithm: String): Service? {
|
||||||
|
return services.getOrPut(Pair(type, algorithm)) {
|
||||||
// Used to work around banning of ConcurrentHashMap in DJVM
|
Optional.ofNullable(superGetService(type, algorithm))
|
||||||
@Suppress("TooGenericExceptionCaught")
|
}.orElse(null)
|
||||||
private val serviceFactory: (String, String) -> Service? = try {
|
|
||||||
// Will throw UnsupportedOperationException in DJVM
|
|
||||||
makeCachingFactory()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
makeFactory()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun superGetService(type: String, algorithm: String): Service? = super.getService(type, algorithm)
|
private fun superGetService(type: String, algorithm: String): Service? = super.getService(type, algorithm)
|
||||||
|
|
||||||
@StubOutForDJVM
|
|
||||||
private fun makeCachingFactory(): Function2<String, String, Service?> {
|
|
||||||
return object : Function2<String, String, Service?> {
|
|
||||||
private val services = ConcurrentHashMap<Pair<String, String>, Optional<Service>>()
|
|
||||||
|
|
||||||
override fun invoke(type: String, algorithm: String): Service? {
|
|
||||||
return services.getOrPut(Pair(type, algorithm)) {
|
|
||||||
Optional.ofNullable(superGetService(type, algorithm))
|
|
||||||
}.orElse(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun makeFactory(): Function2<String, String, Service?> {
|
|
||||||
return object : Function2<String, String, Service?> {
|
|
||||||
override fun invoke(type: String, algorithm: String): Service? {
|
|
||||||
return superGetService(type, algorithm)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@KeepForDJVM
|
|
||||||
object CordaObjectIdentifier {
|
object CordaObjectIdentifier {
|
||||||
// UUID-based OID
|
// UUID-based OID
|
||||||
// TODO define and use an official Corda OID in [CordaOID]. We didn't do yet for backwards compatibility purposes,
|
// TODO define and use an official Corda OID in [CordaOID]. We didn't do yet for backwards compatibility purposes,
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.CordaOID
|
import net.corda.core.CordaOID
|
||||||
import net.corda.core.DeleteForDJVM
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.crypto.internal.AliasPrivateKey
|
import net.corda.core.crypto.internal.AliasPrivateKey
|
||||||
import net.corda.core.crypto.internal.Instances.withSignature
|
import net.corda.core.crypto.internal.Instances.withSignature
|
||||||
|
import net.corda.core.crypto.internal.PublicKeyCache
|
||||||
import net.corda.core.crypto.internal.bouncyCastlePQCProvider
|
import net.corda.core.crypto.internal.bouncyCastlePQCProvider
|
||||||
import net.corda.core.crypto.internal.cordaBouncyCastleProvider
|
import net.corda.core.crypto.internal.cordaBouncyCastleProvider
|
||||||
import net.corda.core.crypto.internal.cordaSecurityProvider
|
import net.corda.core.crypto.internal.cordaSecurityProvider
|
||||||
@ -12,6 +11,7 @@ import net.corda.core.crypto.internal.`id-Curve25519ph`
|
|||||||
import net.corda.core.crypto.internal.providerMap
|
import net.corda.core.crypto.internal.providerMap
|
||||||
import net.corda.core.internal.utilities.PrivateInterner
|
import net.corda.core.internal.utilities.PrivateInterner
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
|
import net.corda.core.utilities.ByteSequence
|
||||||
import net.i2p.crypto.eddsa.EdDSAEngine
|
import net.i2p.crypto.eddsa.EdDSAEngine
|
||||||
import net.i2p.crypto.eddsa.EdDSAPrivateKey
|
import net.i2p.crypto.eddsa.EdDSAPrivateKey
|
||||||
import net.i2p.crypto.eddsa.EdDSAPublicKey
|
import net.i2p.crypto.eddsa.EdDSAPublicKey
|
||||||
@ -81,7 +81,6 @@ import javax.crypto.spec.SecretKeySpec
|
|||||||
* <li>SPHINCS256_SHA512 (SPHINCS-256 hash-based signature scheme using SHA512 as hash algorithm).
|
* <li>SPHINCS256_SHA512 (SPHINCS-256 hash-based signature scheme using SHA512 as hash algorithm).
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
object Crypto {
|
object Crypto {
|
||||||
/**
|
/**
|
||||||
* RSA PKCS#1 signature scheme using SHA256 for message hashing.
|
* RSA PKCS#1 signature scheme using SHA256 for message hashing.
|
||||||
@ -227,7 +226,6 @@ object Crypto {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun supportedSignatureSchemes(): List<SignatureScheme> = ArrayList(signatureSchemeMap.values)
|
fun supportedSignatureSchemes(): List<SignatureScheme> = ArrayList(signatureSchemeMap.values)
|
||||||
|
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun findProvider(name: String): Provider {
|
fun findProvider(name: String): Provider {
|
||||||
return providerMap[name] ?: throw IllegalArgumentException("Unrecognised provider: $name")
|
return providerMap[name] ?: throw IllegalArgumentException("Unrecognised provider: $name")
|
||||||
@ -281,7 +279,7 @@ object Crypto {
|
|||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun findSignatureScheme(key: PublicKey): SignatureScheme {
|
fun findSignatureScheme(key: PublicKey): SignatureScheme {
|
||||||
val keyInfo = SubjectPublicKeyInfo.getInstance(key.encoded)
|
val keyInfo = SubjectPublicKeyInfo.getInstance(encodePublicKey(key))
|
||||||
return findSignatureScheme(keyInfo.algorithm)
|
return findSignatureScheme(keyInfo.algorithm)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,7 +304,6 @@ object Crypto {
|
|||||||
* @throws IllegalArgumentException on not supported scheme or if the given key specification
|
* @throws IllegalArgumentException on not supported scheme or if the given key specification
|
||||||
* is inappropriate for this key factory to produce a private key.
|
* is inappropriate for this key factory to produce a private key.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun decodePrivateKey(encodedKey: ByteArray): PrivateKey {
|
fun decodePrivateKey(encodedKey: ByteArray): PrivateKey {
|
||||||
val keyInfo = PrivateKeyInfo.getInstance(encodedKey)
|
val keyInfo = PrivateKeyInfo.getInstance(encodedKey)
|
||||||
@ -318,7 +315,6 @@ object Crypto {
|
|||||||
return convertIfBCEdDSAPrivateKey(keyFactory.generatePrivate(PKCS8EncodedKeySpec(encodedKey)))
|
return convertIfBCEdDSAPrivateKey(keyFactory.generatePrivate(PKCS8EncodedKeySpec(encodedKey)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteForDJVM
|
|
||||||
private fun decodeAliasPrivateKey(keyInfo: PrivateKeyInfo): PrivateKey {
|
private fun decodeAliasPrivateKey(keyInfo: PrivateKeyInfo): PrivateKey {
|
||||||
val encodable = keyInfo.parsePrivateKey() as DLSequence
|
val encodable = keyInfo.parsePrivateKey() as DLSequence
|
||||||
val derutF8String = encodable.getObjectAt(0)
|
val derutF8String = encodable.getObjectAt(0)
|
||||||
@ -334,7 +330,6 @@ object Crypto {
|
|||||||
* @throws IllegalArgumentException on not supported scheme or if the given key specification
|
* @throws IllegalArgumentException on not supported scheme or if the given key specification
|
||||||
* is inappropriate for this key factory to produce a private key.
|
* is inappropriate for this key factory to produce a private key.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Throws(InvalidKeySpecException::class)
|
@Throws(InvalidKeySpecException::class)
|
||||||
fun decodePrivateKey(schemeCodeName: String, encodedKey: ByteArray): PrivateKey {
|
fun decodePrivateKey(schemeCodeName: String, encodedKey: ByteArray): PrivateKey {
|
||||||
@ -373,10 +368,17 @@ object Crypto {
|
|||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun decodePublicKey(encodedKey: ByteArray): PublicKey {
|
fun decodePublicKey(encodedKey: ByteArray): PublicKey {
|
||||||
val subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(encodedKey)
|
return PublicKeyCache.publicKeyForCachedBytes(ByteSequence.of(encodedKey)) ?: {
|
||||||
val signatureScheme = findSignatureScheme(subjectPublicKeyInfo.algorithm)
|
val subjectPublicKeyInfo = SubjectPublicKeyInfo.getInstance(encodedKey)
|
||||||
val keyFactory = keyFactory(signatureScheme)
|
val signatureScheme = findSignatureScheme(subjectPublicKeyInfo.algorithm)
|
||||||
return convertIfBCEdDSAPublicKey(keyFactory.generatePublic(X509EncodedKeySpec(encodedKey)))
|
val keyFactory = keyFactory(signatureScheme)
|
||||||
|
convertIfBCEdDSAPublicKey(keyFactory.generatePublic(X509EncodedKeySpec(encodedKey)))
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun encodePublicKey(key: PublicKey): ByteArray {
|
||||||
|
return PublicKeyCache.bytesForCachedPublicKey(key)?.bytes ?: key.encoded
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -429,7 +431,6 @@ object Crypto {
|
|||||||
* @throws InvalidKeyException if the private key is invalid.
|
* @throws InvalidKeyException if the private key is invalid.
|
||||||
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Throws(InvalidKeyException::class, SignatureException::class)
|
@Throws(InvalidKeyException::class, SignatureException::class)
|
||||||
fun doSign(privateKey: PrivateKey, clearData: ByteArray): ByteArray = doSign(findSignatureScheme(privateKey), privateKey, clearData)
|
fun doSign(privateKey: PrivateKey, clearData: ByteArray): ByteArray = doSign(findSignatureScheme(privateKey), privateKey, clearData)
|
||||||
@ -444,7 +445,6 @@ object Crypto {
|
|||||||
* @throws InvalidKeyException if the private key is invalid.
|
* @throws InvalidKeyException if the private key is invalid.
|
||||||
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Throws(InvalidKeyException::class, SignatureException::class)
|
@Throws(InvalidKeyException::class, SignatureException::class)
|
||||||
fun doSign(schemeCodeName: String, privateKey: PrivateKey, clearData: ByteArray): ByteArray {
|
fun doSign(schemeCodeName: String, privateKey: PrivateKey, clearData: ByteArray): ByteArray {
|
||||||
@ -461,7 +461,6 @@ object Crypto {
|
|||||||
* @throws InvalidKeyException if the private key is invalid.
|
* @throws InvalidKeyException if the private key is invalid.
|
||||||
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Throws(InvalidKeyException::class, SignatureException::class)
|
@Throws(InvalidKeyException::class, SignatureException::class)
|
||||||
fun doSign(signatureScheme: SignatureScheme, privateKey: PrivateKey, clearData: ByteArray): ByteArray {
|
fun doSign(signatureScheme: SignatureScheme, privateKey: PrivateKey, clearData: ByteArray): ByteArray {
|
||||||
@ -501,7 +500,6 @@ object Crypto {
|
|||||||
* @throws InvalidKeyException if the private key is invalid.
|
* @throws InvalidKeyException if the private key is invalid.
|
||||||
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Throws(InvalidKeyException::class, SignatureException::class)
|
@Throws(InvalidKeyException::class, SignatureException::class)
|
||||||
fun doSign(keyPair: KeyPair, signableData: SignableData): TransactionSignature {
|
fun doSign(keyPair: KeyPair, signableData: SignableData): TransactionSignature {
|
||||||
@ -688,7 +686,6 @@ object Crypto {
|
|||||||
* @return a KeyPair for the requested signature scheme code name.
|
* @return a KeyPair for the requested signature scheme code name.
|
||||||
* @throws IllegalArgumentException if the requested signature scheme is not supported.
|
* @throws IllegalArgumentException if the requested signature scheme is not supported.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun generateKeyPair(schemeCodeName: String): KeyPair = generateKeyPair(findSignatureScheme(schemeCodeName))
|
fun generateKeyPair(schemeCodeName: String): KeyPair = generateKeyPair(findSignatureScheme(schemeCodeName))
|
||||||
|
|
||||||
@ -699,7 +696,6 @@ object Crypto {
|
|||||||
* @return a new [KeyPair] for the requested [SignatureScheme].
|
* @return a new [KeyPair] for the requested [SignatureScheme].
|
||||||
* @throws IllegalArgumentException if the requested signature scheme is not supported.
|
* @throws IllegalArgumentException if the requested signature scheme is not supported.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun generateKeyPair(signatureScheme: SignatureScheme = DEFAULT_SIGNATURE_SCHEME): KeyPair {
|
fun generateKeyPair(signatureScheme: SignatureScheme = DEFAULT_SIGNATURE_SCHEME): KeyPair {
|
||||||
@ -993,7 +989,8 @@ object Crypto {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val interner = PrivateInterner<PublicKey>()
|
private val interner = PrivateInterner<PublicKey>()
|
||||||
private fun internPublicKey(key: PublicKey): PublicKey = interner.intern(key)
|
private fun internPublicKey(key: PublicKey): PublicKey = PublicKeyCache.cachePublicKey(interner.intern(key))
|
||||||
|
|
||||||
|
|
||||||
private fun convertIfBCEdDSAPublicKey(key: PublicKey): PublicKey {
|
private fun convertIfBCEdDSAPublicKey(key: PublicKey): PublicKey {
|
||||||
return internPublicKey(when (key) {
|
return internPublicKey(when (key) {
|
||||||
@ -1049,7 +1046,6 @@ object Crypto {
|
|||||||
* @throws IllegalArgumentException on not supported scheme or if the given key specification
|
* @throws IllegalArgumentException on not supported scheme or if the given key specification
|
||||||
* is inappropriate for a supported key factory to produce a private key.
|
* is inappropriate for a supported key factory to produce a private key.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun toSupportedPrivateKey(key: PrivateKey): PrivateKey {
|
fun toSupportedPrivateKey(key: PrivateKey): PrivateKey {
|
||||||
return when (key) {
|
return when (key) {
|
||||||
@ -1086,7 +1082,6 @@ object Crypto {
|
|||||||
* CRL & CSR checks etc.).
|
* CRL & CSR checks etc.).
|
||||||
*/
|
*/
|
||||||
// TODO: perform all cryptographic operations via Crypto.
|
// TODO: perform all cryptographic operations via Crypto.
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun registerProviders() {
|
fun registerProviders() {
|
||||||
providerMap
|
providerMap
|
||||||
@ -1097,7 +1092,6 @@ object Crypto {
|
|||||||
setBouncyCastleRNG()
|
setBouncyCastleRNG()
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteForDJVM
|
|
||||||
private fun setBouncyCastleRNG() {
|
private fun setBouncyCastleRNG() {
|
||||||
CryptoServicesRegistrar.setSecureRandom(newSecureRandom())
|
CryptoServicesRegistrar.setSecureRandom(newSecureRandom())
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
@file:Suppress("MatchingDeclarationName")
|
@file:Suppress("MatchingDeclarationName")
|
||||||
@file:KeepForDJVM
|
|
||||||
@file:JvmName("CryptoUtils")
|
@file:JvmName("CryptoUtils")
|
||||||
|
|
||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.DeleteForDJVM
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.contracts.PrivacySalt
|
import net.corda.core.contracts.PrivacySalt
|
||||||
import net.corda.core.crypto.internal.platformSecureRandomFactory
|
import net.corda.core.crypto.internal.platformSecureRandomFactory
|
||||||
import net.corda.core.serialization.SerializationDefaults
|
import net.corda.core.serialization.SerializationDefaults
|
||||||
@ -32,7 +28,6 @@ import java.security.SignatureException
|
|||||||
* @throws InvalidKeyException if the private key is invalid.
|
* @throws InvalidKeyException if the private key is invalid.
|
||||||
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@Throws(InvalidKeyException::class, SignatureException::class)
|
@Throws(InvalidKeyException::class, SignatureException::class)
|
||||||
fun PrivateKey.sign(bytesToSign: ByteArray): DigitalSignature = DigitalSignature(Crypto.doSign(this, bytesToSign))
|
fun PrivateKey.sign(bytesToSign: ByteArray): DigitalSignature = DigitalSignature(Crypto.doSign(this, bytesToSign))
|
||||||
|
|
||||||
@ -45,7 +40,6 @@ fun PrivateKey.sign(bytesToSign: ByteArray): DigitalSignature = DigitalSignature
|
|||||||
* @throws InvalidKeyException if the private key is invalid.
|
* @throws InvalidKeyException if the private key is invalid.
|
||||||
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@Throws(InvalidKeyException::class, SignatureException::class)
|
@Throws(InvalidKeyException::class, SignatureException::class)
|
||||||
fun PrivateKey.sign(bytesToSign: ByteArray, publicKey: PublicKey): DigitalSignature.WithKey {
|
fun PrivateKey.sign(bytesToSign: ByteArray, publicKey: PublicKey): DigitalSignature.WithKey {
|
||||||
return DigitalSignature.WithKey(publicKey, this.sign(bytesToSign).bytes)
|
return DigitalSignature.WithKey(publicKey, this.sign(bytesToSign).bytes)
|
||||||
@ -59,12 +53,10 @@ fun PrivateKey.sign(bytesToSign: ByteArray, publicKey: PublicKey): DigitalSignat
|
|||||||
* @throws InvalidKeyException if the private key is invalid.
|
* @throws InvalidKeyException if the private key is invalid.
|
||||||
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@Throws(InvalidKeyException::class, SignatureException::class)
|
@Throws(InvalidKeyException::class, SignatureException::class)
|
||||||
fun KeyPair.sign(bytesToSign: ByteArray): DigitalSignature.WithKey = private.sign(bytesToSign, public)
|
fun KeyPair.sign(bytesToSign: ByteArray): DigitalSignature.WithKey = private.sign(bytesToSign, public)
|
||||||
|
|
||||||
/** Helper function to sign the bytes of [bytesToSign] with a key pair. */
|
/** Helper function to sign the bytes of [bytesToSign] with a key pair. */
|
||||||
@DeleteForDJVM
|
|
||||||
@Throws(InvalidKeyException::class, SignatureException::class)
|
@Throws(InvalidKeyException::class, SignatureException::class)
|
||||||
fun KeyPair.sign(bytesToSign: OpaqueBytes): DigitalSignature.WithKey = sign(bytesToSign.bytes)
|
fun KeyPair.sign(bytesToSign: OpaqueBytes): DigitalSignature.WithKey = sign(bytesToSign.bytes)
|
||||||
|
|
||||||
@ -76,7 +68,6 @@ fun KeyPair.sign(bytesToSign: OpaqueBytes): DigitalSignature.WithKey = sign(byte
|
|||||||
* @throws InvalidKeyException if the private key is invalid.
|
* @throws InvalidKeyException if the private key is invalid.
|
||||||
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
* @throws SignatureException if signing is not possible due to malformed data or private key.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@Throws(InvalidKeyException::class, SignatureException::class)
|
@Throws(InvalidKeyException::class, SignatureException::class)
|
||||||
fun KeyPair.sign(signableData: SignableData): TransactionSignature = Crypto.doSign(this, signableData)
|
fun KeyPair.sign(signableData: SignableData): TransactionSignature = Crypto.doSign(this, signableData)
|
||||||
|
|
||||||
@ -151,7 +142,6 @@ operator fun KeyPair.component1(): PrivateKey = this.private
|
|||||||
operator fun KeyPair.component2(): PublicKey = this.public
|
operator fun KeyPair.component2(): PublicKey = this.public
|
||||||
|
|
||||||
/** A simple wrapper that will make it easier to swap out the signature algorithm we use in future. */
|
/** A simple wrapper that will make it easier to swap out the signature algorithm we use in future. */
|
||||||
@DeleteForDJVM
|
|
||||||
fun generateKeyPair(): KeyPair = Crypto.generateKeyPair()
|
fun generateKeyPair(): KeyPair = Crypto.generateKeyPair()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -196,7 +186,6 @@ fun KeyPair.verify(signatureData: ByteArray, clearData: ByteArray): Boolean = Cr
|
|||||||
* or if no strong [SecureRandom] implementations are available or if Security.getProperty("securerandom.strongAlgorithms") is null or empty,
|
* or if no strong [SecureRandom] implementations are available or if Security.getProperty("securerandom.strongAlgorithms") is null or empty,
|
||||||
* which should never happen and suggests an unusual JVM or non-standard Java library.
|
* which should never happen and suggests an unusual JVM or non-standard Java library.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@Throws(NoSuchAlgorithmException::class)
|
@Throws(NoSuchAlgorithmException::class)
|
||||||
fun secureRandomBytes(numOfBytes: Int): ByteArray = ByteArray(numOfBytes).apply { newSecureRandom().nextBytes(this) }
|
fun secureRandomBytes(numOfBytes: Int): ByteArray = ByteArray(numOfBytes).apply { newSecureRandom().nextBytes(this) }
|
||||||
|
|
||||||
@ -241,7 +230,6 @@ object DummySecureRandom : SecureRandom(DummySecureRandomSpi(), null)
|
|||||||
* or if no strong SecureRandom implementations are available or if Security.getProperty("securerandom.strongAlgorithms") is null or empty,
|
* or if no strong SecureRandom implementations are available or if Security.getProperty("securerandom.strongAlgorithms") is null or empty,
|
||||||
* which should never happen and suggests an unusual JVM or non-standard Java library.
|
* which should never happen and suggests an unusual JVM or non-standard Java library.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@Throws(NoSuchAlgorithmException::class)
|
@Throws(NoSuchAlgorithmException::class)
|
||||||
fun newSecureRandom(): SecureRandom = platformSecureRandomFactory()
|
fun newSecureRandom(): SecureRandom = platformSecureRandomFactory()
|
||||||
|
|
||||||
@ -249,7 +237,6 @@ fun newSecureRandom(): SecureRandom = platformSecureRandomFactory()
|
|||||||
* Returns a random positive non-zero long generated using a secure RNG. This function sacrifies a bit of entropy in order
|
* Returns a random positive non-zero long generated using a secure RNG. This function sacrifies a bit of entropy in order
|
||||||
* to avoid potential bugs where the value is used in a context where negative numbers or zero are not expected.
|
* to avoid potential bugs where the value is used in a context where negative numbers or zero are not expected.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
fun random63BitValue(): Long {
|
fun random63BitValue(): Long {
|
||||||
while (true) {
|
while (true) {
|
||||||
val candidate = Math.abs(newSecureRandom().nextLong())
|
val candidate = Math.abs(newSecureRandom().nextLong())
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for injecting custom digest implementation bypassing JCA.
|
* Interface for injecting custom digest implementation bypassing JCA.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
interface DigestAlgorithm {
|
interface DigestAlgorithm {
|
||||||
/**
|
/**
|
||||||
* Algorithm identifier.
|
* Algorithm identifier.
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.DeleteForDJVM
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.contracts.PrivacySalt
|
import net.corda.core.contracts.PrivacySalt
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.serialization.SerializationDefaults
|
import net.corda.core.serialization.SerializationDefaults
|
||||||
@ -24,13 +22,11 @@ import java.security.MessageDigest
|
|||||||
* @param hashAlgorithm the name of the hash algorithm to be used for the instance
|
* @param hashAlgorithm the name of the hash algorithm to be used for the instance
|
||||||
*/
|
*/
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
@KeepForDJVM
|
|
||||||
data class DigestService(val hashAlgorithm: String) {
|
data class DigestService(val hashAlgorithm: String) {
|
||||||
init {
|
init {
|
||||||
require(hashAlgorithm.isNotEmpty()) { "Hash algorithm name unavailable or not specified" }
|
require(hashAlgorithm.isNotEmpty()) { "Hash algorithm name unavailable or not specified" }
|
||||||
}
|
}
|
||||||
|
|
||||||
@KeepForDJVM
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val NONCE_SIZE = 8
|
private const val NONCE_SIZE = 8
|
||||||
/**
|
/**
|
||||||
@ -114,5 +110,4 @@ data class DigestService(val hashAlgorithm: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@DeleteForDJVM
|
|
||||||
fun DigestService.randomHash(): SecureHash = SecureHash.random(this.hashAlgorithm)
|
fun DigestService.randomHash(): SecureHash = SecureHash.random(this.hashAlgorithm)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import java.security.InvalidKeyException
|
import java.security.InvalidKeyException
|
||||||
@ -9,10 +8,8 @@ import java.security.SignatureException
|
|||||||
|
|
||||||
/** A wrapper around a digital signature. */
|
/** A wrapper around a digital signature. */
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
@KeepForDJVM
|
|
||||||
open class DigitalSignature(bytes: ByteArray) : OpaqueBytes(bytes) {
|
open class DigitalSignature(bytes: ByteArray) : OpaqueBytes(bytes) {
|
||||||
/** A digital signature that identifies who the public key is owned by. */
|
/** A digital signature that identifies who the public key is owned by. */
|
||||||
@KeepForDJVM
|
|
||||||
open class WithKey(val by: PublicKey, bytes: ByteArray) : DigitalSignature(bytes) {
|
open class WithKey(val by: PublicKey, bytes: ByteArray) : DigitalSignature(bytes) {
|
||||||
/**
|
/**
|
||||||
* Utility to simplify the act of verifying a signature.
|
* Utility to simplify the act of verifying a signature.
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,8 +14,9 @@ import java.util.*
|
|||||||
sealed class MerkleTree {
|
sealed class MerkleTree {
|
||||||
abstract val hash: SecureHash
|
abstract val hash: SecureHash
|
||||||
|
|
||||||
@KeepForDJVM data class Leaf(override val hash: SecureHash) : MerkleTree()
|
data class Leaf(override val hash: SecureHash) : MerkleTree()
|
||||||
@KeepForDJVM data class Node(override val hash: SecureHash, val left: MerkleTree, val right: MerkleTree) : MerkleTree()
|
|
||||||
|
data class Node(override val hash: SecureHash, val left: MerkleTree, val right: MerkleTree) : MerkleTree()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private fun isPow2(num: Int): Boolean = num and (num - 1) == 0
|
private fun isPow2(num: Int): Boolean = num and (num - 1) == 0
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.identity.AnonymousParty
|
import net.corda.core.identity.AnonymousParty
|
||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
|
|
||||||
@KeepForDJVM
|
|
||||||
object NullKeys {
|
object NullKeys {
|
||||||
object NullPublicKey : PublicKey, Comparable<PublicKey> {
|
object NullPublicKey : PublicKey, Comparable<PublicKey> {
|
||||||
override fun getAlgorithm() = "NULL"
|
override fun getAlgorithm() = "NULL"
|
||||||
|
@ -2,12 +2,10 @@ package net.corda.core.crypto
|
|||||||
|
|
||||||
import net.corda.core.CordaException
|
import net.corda.core.CordaException
|
||||||
import net.corda.core.CordaInternal
|
import net.corda.core.CordaInternal
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.serialization.DeprecatedConstructorForDeserialization
|
import net.corda.core.serialization.DeprecatedConstructorForDeserialization
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@KeepForDJVM
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
class MerkleTreeException(val reason: String) : CordaException("Partial Merkle Tree exception. Reason: $reason")
|
class MerkleTreeException(val reason: String) : CordaException("Partial Merkle Tree exception. Reason: $reason")
|
||||||
|
|
||||||
@ -45,7 +43,6 @@ class MerkleTreeException(val reason: String) : CordaException("Partial Merkle T
|
|||||||
* (there can be a difference in obtained leaves ordering - that's why it's a set comparison not hashing leaves into a tree).
|
* (there can be a difference in obtained leaves ordering - that's why it's a set comparison not hashing leaves into a tree).
|
||||||
* If both equalities hold, we can assume that l3 and l5 belong to the transaction with root h15.
|
* If both equalities hold, we can assume that l3 and l5 belong to the transaction with root h15.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
class PartialMerkleTree(val root: PartialTree) {
|
class PartialMerkleTree(val root: PartialTree) {
|
||||||
/**
|
/**
|
||||||
@ -57,9 +54,9 @@ class PartialMerkleTree(val root: PartialTree) {
|
|||||||
*/
|
*/
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
sealed class PartialTree {
|
sealed class PartialTree {
|
||||||
@KeepForDJVM data class IncludedLeaf(val hash: SecureHash) : PartialTree()
|
data class IncludedLeaf(val hash: SecureHash) : PartialTree()
|
||||||
@KeepForDJVM data class Leaf(val hash: SecureHash) : PartialTree()
|
data class Leaf(val hash: SecureHash) : PartialTree()
|
||||||
@KeepForDJVM data class Node(val left: PartialTree, val right: PartialTree, val hashAlgorithm: String? = SecureHash.SHA2_256) : PartialTree(){
|
data class Node(val left: PartialTree, val right: PartialTree, val hashAlgorithm: String? = SecureHash.SHA2_256) : PartialTree() {
|
||||||
/**
|
/**
|
||||||
* Old version of [PartialTree.Node] constructor for ABI compatibility.
|
* Old version of [PartialTree.Node] constructor for ABI compatibility.
|
||||||
*/
|
*/
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
@file:Suppress("TooManyFunctions", "MagicNumber")
|
@file:Suppress("TooManyFunctions", "MagicNumber")
|
||||||
@file:KeepForDJVM
|
|
||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import io.netty.util.concurrent.FastThreadLocal
|
import io.netty.util.concurrent.FastThreadLocal
|
||||||
import net.corda.core.CordaInternal
|
import net.corda.core.CordaInternal
|
||||||
import net.corda.core.DeleteForDJVM
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.crypto.internal.DigestAlgorithmFactory
|
import net.corda.core.crypto.internal.DigestAlgorithmFactory
|
||||||
import net.corda.core.internal.utilities.Internable
|
import net.corda.core.internal.utilities.Internable
|
||||||
import net.corda.core.internal.utilities.PrivateInterner
|
import net.corda.core.internal.utilities.PrivateInterner
|
||||||
@ -13,7 +10,6 @@ import net.corda.core.serialization.CordaSerializable
|
|||||||
import net.corda.core.utilities.OpaqueBytes
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
import net.corda.core.utilities.parseAsHex
|
import net.corda.core.utilities.parseAsHex
|
||||||
import net.corda.core.utilities.toHexString
|
import net.corda.core.utilities.toHexString
|
||||||
import java.nio.ByteBuffer
|
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import java.util.concurrent.ConcurrentMap
|
import java.util.concurrent.ConcurrentMap
|
||||||
@ -23,7 +19,6 @@ import java.util.function.Supplier
|
|||||||
* Container for a cryptographically secure hash value.
|
* Container for a cryptographically secure hash value.
|
||||||
* Provides utilities for generating a cryptographic hash using different algorithms (currently only SHA-256 supported).
|
* Provides utilities for generating a cryptographic hash using different algorithms (currently only SHA-256 supported).
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
sealed class SecureHash(bytes: ByteArray) : OpaqueBytes(bytes) {
|
sealed class SecureHash(bytes: ByteArray) : OpaqueBytes(bytes) {
|
||||||
/** SHA-256 is part of the SHA-2 hash function family. Generated hash is fixed size, 256-bits (32-bytes). */
|
/** SHA-256 is part of the SHA-2 hash function family. Generated hash is fixed size, 256-bits (32-bytes). */
|
||||||
@ -39,9 +34,10 @@ sealed class SecureHash(bytes: ByteArray) : OpaqueBytes(bytes) {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is an efficient hashCode, because there is no point in performing a hash calculation on a cryptographic hash.
|
override fun hashCode(): Int {
|
||||||
// It just takes the first 4 bytes and transforms them into an Int.
|
// Hash code not overridden on purpose (super class impl will do), but don't delete or have to deal with detekt and API checker.
|
||||||
override fun hashCode() = ByteBuffer.wrap(bytes).int
|
return super.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert the hash value to an uppercase hexadecimal [String].
|
* Convert the hash value to an uppercase hexadecimal [String].
|
||||||
@ -62,7 +58,10 @@ sealed class SecureHash(bytes: ByteArray) : OpaqueBytes(bytes) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun hashCode() = ByteBuffer.wrap(bytes).int
|
override fun hashCode(): Int {
|
||||||
|
// Hash code not overridden on purpose (super class impl will do), but don't delete or have to deal with detekt and API checker.
|
||||||
|
return super.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "$algorithm$DELIMITER${toHexString()}"
|
return "$algorithm$DELIMITER${toHexString()}"
|
||||||
@ -288,14 +287,12 @@ sealed class SecureHash(bytes: ByteArray) : OpaqueBytes(bytes) {
|
|||||||
/**
|
/**
|
||||||
* Generates a random SHA-256 value.
|
* Generates a random SHA-256 value.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun randomSHA256() = sha256(secureRandomBytes(32))
|
fun randomSHA256() = sha256(secureRandomBytes(32))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a random hash value.
|
* Generates a random hash value.
|
||||||
*/
|
*/
|
||||||
@DeleteForDJVM
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun random(algorithm: String): SecureHash {
|
fun random(algorithm: String): SecureHash {
|
||||||
return if (algorithm == SHA2_256) {
|
return if (algorithm == SHA2_256) {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -13,5 +12,4 @@ import net.corda.core.serialization.CordaSerializable
|
|||||||
* @param signatureMetadata meta data required.
|
* @param signatureMetadata meta data required.
|
||||||
*/
|
*/
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
@KeepForDJVM
|
|
||||||
data class SignableData(val txId: SecureHash, val signatureMetadata: SignatureMetadata)
|
data class SignableData(val txId: SecureHash, val signatureMetadata: SignatureMetadata)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -13,5 +12,4 @@ import net.corda.core.serialization.CordaSerializable
|
|||||||
* @param schemeNumberID number id of the signature scheme used based on signer's key-pair, see [SignatureScheme.schemeNumberID].
|
* @param schemeNumberID number id of the signature scheme used based on signer's key-pair, see [SignatureScheme.schemeNumberID].
|
||||||
*/
|
*/
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
@KeepForDJVM
|
|
||||||
data class SignatureMetadata(val platformVersion: Int, val schemeNumberID: Int)
|
data class SignatureMetadata(val platformVersion: Int, val schemeNumberID: Int)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import org.bouncycastle.asn1.x509.AlgorithmIdentifier
|
import org.bouncycastle.asn1.x509.AlgorithmIdentifier
|
||||||
import java.security.KeyFactory
|
import java.security.KeyFactory
|
||||||
import java.security.Signature
|
import java.security.Signature
|
||||||
@ -22,7 +21,6 @@ import java.security.spec.AlgorithmParameterSpec
|
|||||||
* @param keySize the private key size (currently used for RSA only).
|
* @param keySize the private key size (currently used for RSA only).
|
||||||
* @param desc a human-readable description for this scheme.
|
* @param desc a human-readable description for this scheme.
|
||||||
*/
|
*/
|
||||||
@KeepForDJVM
|
|
||||||
data class SignatureScheme(
|
data class SignatureScheme(
|
||||||
val schemeNumberID: Int,
|
val schemeNumberID: Int,
|
||||||
val schemeCodeName: String,
|
val schemeCodeName: String,
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package net.corda.core.crypto
|
package net.corda.core.crypto
|
||||||
|
|
||||||
import net.corda.core.KeepForDJVM
|
|
||||||
import net.corda.core.internal.uncheckedCast
|
import net.corda.core.internal.uncheckedCast
|
||||||
import net.corda.core.serialization.CordaSerializable
|
import net.corda.core.serialization.CordaSerializable
|
||||||
import net.corda.core.serialization.SerializedBytes
|
import net.corda.core.serialization.SerializedBytes
|
||||||
@ -15,7 +14,6 @@ import java.security.SignatureException
|
|||||||
* @param sig the (unverified) signature for the data.
|
* @param sig the (unverified) signature for the data.
|
||||||
*/
|
*/
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
@KeepForDJVM
|
|
||||||
open class SignedData<T : Any>(val raw: SerializedBytes<T>, val sig: DigitalSignature.WithKey) {
|
open class SignedData<T : Any>(val raw: SerializedBytes<T>, val sig: DigitalSignature.WithKey) {
|
||||||
/**
|
/**
|
||||||
* Return the deserialized data if the signature can be verified.
|
* Return the deserialized data if the signature can be verified.
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user