mirror of
https://github.com/corda/corda.git
synced 2024-12-19 21:17:58 +00:00
Merge branch 'release/os/4.5' into dan/merge-4.5-into-feature-branch
# Conflicts: # node/src/main/kotlin/net/corda/node/services/statemachine/transitions/StartedFlowTransition.kt
This commit is contained in:
commit
ac3f880ae4
@ -6818,6 +6818,392 @@ public static final class net.corda.core.utilities.UuidGenerator$Companion exten
|
||||
public interface net.corda.core.utilities.VariablePropertyDelegate extends net.corda.core.utilities.PropertyDelegate
|
||||
public abstract void setValue(Object, kotlin.reflect.KProperty<?>, T)
|
||||
##
|
||||
public final class net.corda.testing.contracts.DummyContract extends java.lang.Object implements net.corda.core.contracts.Contract
|
||||
public <init>()
|
||||
public <init>(Object)
|
||||
public <init>(Object, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
@Nullable
|
||||
public final Object component1()
|
||||
@NotNull
|
||||
public final net.corda.testing.contracts.DummyContract copy(Object)
|
||||
public boolean equals(Object)
|
||||
@NotNull
|
||||
public static final net.corda.core.transactions.TransactionBuilder generateInitial(int, net.corda.core.identity.Party, net.corda.core.contracts.PartyAndReference, net.corda.core.contracts.PartyAndReference...)
|
||||
@Nullable
|
||||
public final Object getBlank()
|
||||
@NotNull
|
||||
public final String getPROGRAM_ID()
|
||||
public int hashCode()
|
||||
@NotNull
|
||||
public static final net.corda.core.transactions.TransactionBuilder move(java.util.List<net.corda.core.contracts.StateAndRef<net.corda.testing.contracts.DummyContract$SingleOwnerState>>, net.corda.core.identity.AbstractParty)
|
||||
@NotNull
|
||||
public static final net.corda.core.transactions.TransactionBuilder move(net.corda.core.contracts.StateAndRef<net.corda.testing.contracts.DummyContract$SingleOwnerState>, net.corda.core.identity.AbstractParty)
|
||||
@NotNull
|
||||
public String toString()
|
||||
public void verify(net.corda.core.transactions.LedgerTransaction)
|
||||
public static final net.corda.testing.contracts.DummyContract$Companion Companion
|
||||
@NotNull
|
||||
public static final String PROGRAM_ID = "net.corda.testing.contracts.DummyContract"
|
||||
##
|
||||
public static interface net.corda.testing.contracts.DummyContract$Commands extends net.corda.core.contracts.CommandData
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContract$Commands$Create extends net.corda.core.contracts.TypeOnlyCommandData implements net.corda.testing.contracts.DummyContract$Commands
|
||||
public <init>()
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContract$Commands$Move extends net.corda.core.contracts.TypeOnlyCommandData implements net.corda.testing.contracts.DummyContract$Commands
|
||||
public <init>()
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContract$Companion extends java.lang.Object
|
||||
public <init>(kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
@NotNull
|
||||
public final net.corda.core.transactions.TransactionBuilder generateInitial(int, net.corda.core.identity.Party, net.corda.core.contracts.PartyAndReference, net.corda.core.contracts.PartyAndReference...)
|
||||
@NotNull
|
||||
public final net.corda.core.transactions.TransactionBuilder move(java.util.List<net.corda.core.contracts.StateAndRef<net.corda.testing.contracts.DummyContract$SingleOwnerState>>, net.corda.core.identity.AbstractParty)
|
||||
@NotNull
|
||||
public final net.corda.core.transactions.TransactionBuilder move(net.corda.core.contracts.StateAndRef<net.corda.testing.contracts.DummyContract$SingleOwnerState>, net.corda.core.identity.AbstractParty)
|
||||
##
|
||||
@DoNotImplement
|
||||
public static final class net.corda.testing.contracts.DummyContract$MultiOwnerState extends java.lang.Object implements net.corda.testing.contracts.DummyContract$State
|
||||
public <init>(int, java.util.List<? extends net.corda.core.identity.AbstractParty>)
|
||||
public <init>(int, java.util.List, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
public final int component1()
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.core.identity.AbstractParty> component2()
|
||||
@NotNull
|
||||
public final net.corda.testing.contracts.DummyContract$MultiOwnerState copy(int, java.util.List<? extends net.corda.core.identity.AbstractParty>)
|
||||
public boolean equals(Object)
|
||||
public int getMagicNumber()
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.core.identity.AbstractParty> getOwners()
|
||||
@NotNull
|
||||
public java.util.List<net.corda.core.identity.AbstractParty> getParticipants()
|
||||
public int hashCode()
|
||||
@NotNull
|
||||
public String toString()
|
||||
##
|
||||
@DoNotImplement
|
||||
public static final class net.corda.testing.contracts.DummyContract$SingleOwnerState extends java.lang.Object implements net.corda.core.contracts.OwnableState, net.corda.testing.contracts.DummyContract$State
|
||||
public <init>(int, net.corda.core.identity.AbstractParty)
|
||||
public <init>(int, net.corda.core.identity.AbstractParty, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
public final int component1()
|
||||
@NotNull
|
||||
public final net.corda.core.identity.AbstractParty component2()
|
||||
@NotNull
|
||||
public final net.corda.testing.contracts.DummyContract$SingleOwnerState copy(int, net.corda.core.identity.AbstractParty)
|
||||
public boolean equals(Object)
|
||||
public int getMagicNumber()
|
||||
@NotNull
|
||||
public net.corda.core.identity.AbstractParty getOwner()
|
||||
@NotNull
|
||||
public java.util.List<net.corda.core.identity.AbstractParty> getParticipants()
|
||||
public int hashCode()
|
||||
@NotNull
|
||||
public String toString()
|
||||
@NotNull
|
||||
public net.corda.core.contracts.CommandAndState withNewOwner(net.corda.core.identity.AbstractParty)
|
||||
##
|
||||
@DoNotImplement
|
||||
public static interface net.corda.testing.contracts.DummyContract$State extends net.corda.core.contracts.ContractState
|
||||
public abstract int getMagicNumber()
|
||||
##
|
||||
public final class net.corda.testing.contracts.DummyContractV2 extends java.lang.Object implements net.corda.core.contracts.UpgradedContractWithLegacyConstraint
|
||||
public <init>()
|
||||
@NotNull
|
||||
public String getLegacyContract()
|
||||
@NotNull
|
||||
public net.corda.core.contracts.AttachmentConstraint getLegacyContractConstraint()
|
||||
@NotNull
|
||||
public net.corda.testing.contracts.DummyContractV2$State upgrade(net.corda.testing.contracts.DummyContract$State)
|
||||
public void verify(net.corda.core.transactions.LedgerTransaction)
|
||||
public static final net.corda.testing.contracts.DummyContractV2$Companion Companion
|
||||
@NotNull
|
||||
public static final String PROGRAM_ID = "net.corda.testing.contracts.DummyContractV2"
|
||||
##
|
||||
public static interface net.corda.testing.contracts.DummyContractV2$Commands extends net.corda.core.contracts.CommandData
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContractV2$Commands$Create extends net.corda.core.contracts.TypeOnlyCommandData implements net.corda.testing.contracts.DummyContractV2$Commands
|
||||
public <init>()
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContractV2$Commands$Move extends net.corda.core.contracts.TypeOnlyCommandData implements net.corda.testing.contracts.DummyContractV2$Commands
|
||||
public <init>()
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContractV2$Companion extends java.lang.Object
|
||||
public <init>(kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContractV2$State extends java.lang.Object implements net.corda.core.contracts.ContractState
|
||||
public <init>(int, java.util.List<? extends net.corda.core.identity.AbstractParty>)
|
||||
public <init>(int, java.util.List, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
public final int component1()
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.core.identity.AbstractParty> component2()
|
||||
@NotNull
|
||||
public final net.corda.testing.contracts.DummyContractV2$State copy(int, java.util.List<? extends net.corda.core.identity.AbstractParty>)
|
||||
public boolean equals(Object)
|
||||
public final int getMagicNumber()
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.core.identity.AbstractParty> getOwners()
|
||||
@NotNull
|
||||
public java.util.List<net.corda.core.identity.AbstractParty> getParticipants()
|
||||
public int hashCode()
|
||||
@NotNull
|
||||
public String toString()
|
||||
##
|
||||
public final class net.corda.testing.contracts.DummyContractV3 extends java.lang.Object implements net.corda.core.contracts.UpgradedContractWithLegacyConstraint
|
||||
public <init>()
|
||||
@NotNull
|
||||
public String getLegacyContract()
|
||||
@NotNull
|
||||
public net.corda.core.contracts.AttachmentConstraint getLegacyContractConstraint()
|
||||
@NotNull
|
||||
public net.corda.testing.contracts.DummyContractV3$State upgrade(net.corda.testing.contracts.DummyContractV2$State)
|
||||
public void verify(net.corda.core.transactions.LedgerTransaction)
|
||||
public static final net.corda.testing.contracts.DummyContractV3$Companion Companion
|
||||
@NotNull
|
||||
public static final String PROGRAM_ID = "net.corda.testing.contracts.DummyContractV3"
|
||||
##
|
||||
public static interface net.corda.testing.contracts.DummyContractV3$Commands extends net.corda.core.contracts.CommandData
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContractV3$Commands$Create extends net.corda.core.contracts.TypeOnlyCommandData implements net.corda.testing.contracts.DummyContractV3$Commands
|
||||
public <init>()
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContractV3$Commands$Move extends net.corda.core.contracts.TypeOnlyCommandData implements net.corda.testing.contracts.DummyContractV3$Commands
|
||||
public <init>()
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContractV3$Companion extends java.lang.Object
|
||||
public <init>(kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContractV3$State extends java.lang.Object implements net.corda.core.contracts.ContractState
|
||||
public <init>(int, java.util.List<? extends net.corda.core.identity.AbstractParty>)
|
||||
public <init>(int, java.util.List, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
public final int component1()
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.core.identity.AbstractParty> component2()
|
||||
@NotNull
|
||||
public final net.corda.testing.contracts.DummyContractV3$State copy(int, java.util.List<? extends net.corda.core.identity.AbstractParty>)
|
||||
public boolean equals(Object)
|
||||
public final int getMagicNumber()
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.core.identity.AbstractParty> getOwners()
|
||||
@NotNull
|
||||
public java.util.List<net.corda.core.identity.AbstractParty> getParticipants()
|
||||
public int hashCode()
|
||||
@NotNull
|
||||
public String toString()
|
||||
##
|
||||
@BelongsToContract
|
||||
public final class net.corda.testing.contracts.DummyState extends java.lang.Object implements net.corda.core.contracts.ContractState
|
||||
public <init>()
|
||||
public <init>(int)
|
||||
public <init>(int, java.util.List<? extends net.corda.core.identity.AbstractParty>)
|
||||
public <init>(int, java.util.List, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
public final int component1()
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.core.identity.AbstractParty> component2()
|
||||
@NotNull
|
||||
public final net.corda.testing.contracts.DummyState copy(int)
|
||||
@NotNull
|
||||
public final net.corda.testing.contracts.DummyState copy(int, java.util.List<? extends net.corda.core.identity.AbstractParty>)
|
||||
public boolean equals(Object)
|
||||
public final int getMagicNumber()
|
||||
@NotNull
|
||||
public java.util.List<net.corda.core.identity.AbstractParty> getParticipants()
|
||||
public int hashCode()
|
||||
@NotNull
|
||||
public String toString()
|
||||
##
|
||||
public final class net.corda.testing.core.DummyCommandData extends net.corda.core.contracts.TypeOnlyCommandData
|
||||
public static final net.corda.testing.core.DummyCommandData INSTANCE
|
||||
##
|
||||
public final class net.corda.testing.core.Expect extends java.lang.Object
|
||||
public <init>(Class<T>, kotlin.jvm.functions.Function1<? super T, Boolean>, kotlin.jvm.functions.Function1<? super T, kotlin.Unit>)
|
||||
@NotNull
|
||||
public final Class<T> component1()
|
||||
@NotNull
|
||||
public final kotlin.jvm.functions.Function1<T, Boolean> component2()
|
||||
@NotNull
|
||||
public final kotlin.jvm.functions.Function1<T, kotlin.Unit> component3()
|
||||
@NotNull
|
||||
public final net.corda.testing.core.Expect<E, T> copy(Class<T>, kotlin.jvm.functions.Function1<? super T, Boolean>, kotlin.jvm.functions.Function1<? super T, kotlin.Unit>)
|
||||
public boolean equals(Object)
|
||||
@NotNull
|
||||
public final Class<T> getClazz()
|
||||
@NotNull
|
||||
public final kotlin.jvm.functions.Function1<T, kotlin.Unit> getExpectClosure()
|
||||
@NotNull
|
||||
public final kotlin.jvm.functions.Function1<T, Boolean> getMatch()
|
||||
public int hashCode()
|
||||
@NotNull
|
||||
public String toString()
|
||||
##
|
||||
@DoNotImplement
|
||||
public abstract class net.corda.testing.core.ExpectCompose extends java.lang.Object
|
||||
public <init>(kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
##
|
||||
@DoNotImplement
|
||||
public static final class net.corda.testing.core.ExpectCompose$Parallel extends net.corda.testing.core.ExpectCompose
|
||||
public <init>(java.util.List<? extends net.corda.testing.core.ExpectCompose<? extends E>>)
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.testing.core.ExpectCompose<E>> getParallel()
|
||||
##
|
||||
@DoNotImplement
|
||||
public static final class net.corda.testing.core.ExpectCompose$Sequential extends net.corda.testing.core.ExpectCompose
|
||||
public <init>(java.util.List<? extends net.corda.testing.core.ExpectCompose<? extends E>>)
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.testing.core.ExpectCompose<E>> getSequence()
|
||||
##
|
||||
@DoNotImplement
|
||||
public static final class net.corda.testing.core.ExpectCompose$Single extends net.corda.testing.core.ExpectCompose
|
||||
public <init>(net.corda.testing.core.Expect<? extends E, T>)
|
||||
@NotNull
|
||||
public final net.corda.testing.core.Expect<E, T> getExpect()
|
||||
##
|
||||
public static final class net.corda.testing.core.ExpectComposeState$Companion extends java.lang.Object
|
||||
public <init>(kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
@NotNull
|
||||
public final net.corda.testing.core.ExpectComposeState<E> fromExpectCompose(net.corda.testing.core.ExpectCompose<? extends E>)
|
||||
##
|
||||
public static final class net.corda.testing.core.ExpectComposeState$Finished extends net.corda.testing.core.ExpectComposeState
|
||||
public <init>()
|
||||
@NotNull
|
||||
public java.util.List<Class<E>> getExpectedEvents()
|
||||
@Nullable
|
||||
public Void nextState(E)
|
||||
##
|
||||
public static final class net.corda.testing.core.ExpectComposeState$Parallel extends net.corda.testing.core.ExpectComposeState
|
||||
public <init>(net.corda.testing.core.ExpectCompose$Parallel<? extends E>, java.util.List<? extends net.corda.testing.core.ExpectComposeState<E>>)
|
||||
@NotNull
|
||||
public java.util.List<Class<? extends E>> getExpectedEvents()
|
||||
@NotNull
|
||||
public final net.corda.testing.core.ExpectCompose$Parallel<E> getParallel()
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.testing.core.ExpectComposeState<E>> getStates()
|
||||
@Nullable
|
||||
public kotlin.Pair<kotlin.jvm.functions.Function0<kotlin.Unit>, net.corda.testing.core.ExpectComposeState<E>> nextState(E)
|
||||
##
|
||||
public static final class net.corda.testing.core.ExpectComposeState$Sequential extends net.corda.testing.core.ExpectComposeState
|
||||
public <init>(net.corda.testing.core.ExpectCompose$Sequential<? extends E>, int, net.corda.testing.core.ExpectComposeState<E>)
|
||||
@NotNull
|
||||
public java.util.List<Class<? extends E>> getExpectedEvents()
|
||||
public final int getIndex()
|
||||
@NotNull
|
||||
public final net.corda.testing.core.ExpectCompose$Sequential<E> getSequential()
|
||||
@NotNull
|
||||
public final net.corda.testing.core.ExpectComposeState<E> getState()
|
||||
@Nullable
|
||||
public kotlin.Pair<kotlin.jvm.functions.Function0<kotlin.Unit>, net.corda.testing.core.ExpectComposeState<E>> nextState(E)
|
||||
##
|
||||
public static final class net.corda.testing.core.ExpectComposeState$Single extends net.corda.testing.core.ExpectComposeState
|
||||
public <init>(net.corda.testing.core.ExpectCompose$Single<? extends E, T>)
|
||||
@NotNull
|
||||
public java.util.List<Class<T>> getExpectedEvents()
|
||||
@NotNull
|
||||
public final net.corda.testing.core.ExpectCompose$Single<E, T> getSingle()
|
||||
@Nullable
|
||||
public kotlin.Pair<kotlin.jvm.functions.Function0<kotlin.Unit>, net.corda.testing.core.ExpectComposeState<E>> nextState(E)
|
||||
##
|
||||
public final class net.corda.testing.core.ExpectKt extends java.lang.Object
|
||||
@NotNull
|
||||
public static final net.corda.testing.core.ExpectCompose<E> expect(Class<E>, kotlin.jvm.functions.Function1<? super E, Boolean>, kotlin.jvm.functions.Function1<? super E, kotlin.Unit>)
|
||||
public static final void expectEvents(Iterable<? extends E>, boolean, kotlin.jvm.functions.Function0<? extends net.corda.testing.core.ExpectCompose<? extends E>>)
|
||||
public static final void expectEvents(rx.Observable<E>, boolean, kotlin.jvm.functions.Function0<? extends net.corda.testing.core.ExpectCompose<? extends E>>)
|
||||
public static final void genericExpectEvents(S, boolean, kotlin.jvm.functions.Function2<? super S, ? super kotlin.jvm.functions.Function1<? super E, kotlin.Unit>, kotlin.Unit>, kotlin.jvm.functions.Function0<? extends net.corda.testing.core.ExpectCompose<? extends E>>)
|
||||
@NotNull
|
||||
public static final net.corda.testing.core.ExpectCompose<E> parallel(java.util.List<? extends net.corda.testing.core.ExpectCompose<? extends E>>)
|
||||
@NotNull
|
||||
public static final net.corda.testing.core.ExpectCompose<E> parallel(net.corda.testing.core.ExpectCompose<? extends E>...)
|
||||
@NotNull
|
||||
public static final net.corda.testing.core.ExpectCompose<E> replicate(int, kotlin.jvm.functions.Function1<? super Integer, ? extends net.corda.testing.core.ExpectCompose<? extends E>>)
|
||||
@NotNull
|
||||
public static final net.corda.testing.core.ExpectCompose<E> sequence(java.util.List<? extends net.corda.testing.core.ExpectCompose<? extends E>>)
|
||||
@NotNull
|
||||
public static final net.corda.testing.core.ExpectCompose<E> sequence(net.corda.testing.core.ExpectCompose<? extends E>...)
|
||||
##
|
||||
public final class net.corda.testing.core.SerializationEnvironmentRule extends java.lang.Object implements org.junit.rules.TestRule
|
||||
public <init>()
|
||||
public <init>(boolean)
|
||||
public <init>(boolean, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
@NotNull
|
||||
public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement, org.junit.runner.Description)
|
||||
@NotNull
|
||||
public final net.corda.core.serialization.SerializationFactory getSerializationFactory()
|
||||
public static final net.corda.testing.core.SerializationEnvironmentRule$Companion Companion
|
||||
##
|
||||
public static final class net.corda.testing.core.SerializationEnvironmentRule$Companion extends java.lang.Object
|
||||
public <init>(kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
##
|
||||
public final class net.corda.testing.core.TestConstants extends java.lang.Object
|
||||
@NotNull
|
||||
public static final net.corda.core.contracts.Command<net.corda.core.contracts.TypeOnlyCommandData> dummyCommand(java.security.PublicKey...)
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.CordaX500Name ALICE_NAME
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.CordaX500Name BOB_NAME
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.CordaX500Name BOC_NAME
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.CordaX500Name CHARLIE_NAME
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.CordaX500Name DUMMY_BANK_A_NAME
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.CordaX500Name DUMMY_BANK_B_NAME
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.CordaX500Name DUMMY_BANK_C_NAME
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.CordaX500Name DUMMY_NOTARY_NAME
|
||||
public static final int MAX_MESSAGE_SIZE = 10485760
|
||||
##
|
||||
public final class net.corda.testing.core.TestIdentity extends java.lang.Object
|
||||
public <init>(net.corda.core.identity.CordaX500Name)
|
||||
public <init>(net.corda.core.identity.CordaX500Name, long)
|
||||
public <init>(net.corda.core.identity.CordaX500Name, long, net.corda.core.crypto.SignatureScheme)
|
||||
public <init>(net.corda.core.identity.CordaX500Name, long, net.corda.core.crypto.SignatureScheme, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
public <init>(net.corda.core.identity.CordaX500Name, java.security.KeyPair)
|
||||
public <init>(net.corda.core.identity.CordaX500Name, net.corda.core.crypto.SignatureScheme)
|
||||
public <init>(net.corda.core.identity.CordaX500Name, net.corda.core.crypto.SignatureScheme, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
@NotNull
|
||||
public static final net.corda.testing.core.TestIdentity fresh(String)
|
||||
@NotNull
|
||||
public static final net.corda.testing.core.TestIdentity fresh(String, net.corda.core.crypto.SignatureScheme)
|
||||
@NotNull
|
||||
public final net.corda.core.identity.PartyAndCertificate getIdentity()
|
||||
@NotNull
|
||||
public final java.security.KeyPair getKeyPair()
|
||||
@NotNull
|
||||
public final net.corda.core.identity.CordaX500Name getName()
|
||||
@NotNull
|
||||
public final net.corda.core.identity.Party getParty()
|
||||
@NotNull
|
||||
public final java.security.PublicKey getPublicKey()
|
||||
@NotNull
|
||||
public final net.corda.core.contracts.PartyAndReference ref(byte...)
|
||||
public static final net.corda.testing.core.TestIdentity$Companion Companion
|
||||
##
|
||||
public static final class net.corda.testing.core.TestIdentity$Companion extends java.lang.Object
|
||||
public <init>(kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
@NotNull
|
||||
public final net.corda.testing.core.TestIdentity fresh(String)
|
||||
@NotNull
|
||||
public final net.corda.testing.core.TestIdentity fresh(String, net.corda.core.crypto.SignatureScheme)
|
||||
##
|
||||
public final class net.corda.testing.core.TestUtils extends java.lang.Object
|
||||
@NotNull
|
||||
public static final net.corda.core.utilities.NetworkHostAndPort freeLocalHostAndPort()
|
||||
public static final int freePort()
|
||||
@NotNull
|
||||
public static final net.corda.core.contracts.StateRef generateStateRef()
|
||||
@NotNull
|
||||
public static final java.util.List<net.corda.core.utilities.NetworkHostAndPort> getFreeLocalPorts(String, int)
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.PartyAndCertificate getTestPartyAndCertificate(net.corda.core.identity.CordaX500Name, java.security.PublicKey)
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.PartyAndCertificate getTestPartyAndCertificate(net.corda.core.identity.Party)
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.CordaX500Name makeUnique(net.corda.core.identity.CordaX500Name)
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.Party singleIdentity(net.corda.core.node.NodeInfo)
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.PartyAndCertificate singleIdentityAndCert(net.corda.core.node.NodeInfo)
|
||||
##
|
||||
public final class net.corda.client.jackson.JacksonSupport extends java.lang.Object
|
||||
@NotNull
|
||||
public static final com.fasterxml.jackson.databind.ObjectMapper createDefaultMapper(net.corda.core.messaging.CordaRPCOps)
|
||||
@ -8148,392 +8534,6 @@ public static class net.corda.finance.test.SampleCashSchemaV3$PersistentCashStat
|
||||
public void setParticipants(java.util.Set<net.corda.core.identity.AbstractParty>)
|
||||
public void setPennies(long)
|
||||
##
|
||||
public final class net.corda.testing.contracts.DummyContract extends java.lang.Object implements net.corda.core.contracts.Contract
|
||||
public <init>()
|
||||
public <init>(Object)
|
||||
public <init>(Object, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
@Nullable
|
||||
public final Object component1()
|
||||
@NotNull
|
||||
public final net.corda.testing.contracts.DummyContract copy(Object)
|
||||
public boolean equals(Object)
|
||||
@NotNull
|
||||
public static final net.corda.core.transactions.TransactionBuilder generateInitial(int, net.corda.core.identity.Party, net.corda.core.contracts.PartyAndReference, net.corda.core.contracts.PartyAndReference...)
|
||||
@Nullable
|
||||
public final Object getBlank()
|
||||
@NotNull
|
||||
public final String getPROGRAM_ID()
|
||||
public int hashCode()
|
||||
@NotNull
|
||||
public static final net.corda.core.transactions.TransactionBuilder move(java.util.List<net.corda.core.contracts.StateAndRef<net.corda.testing.contracts.DummyContract$SingleOwnerState>>, net.corda.core.identity.AbstractParty)
|
||||
@NotNull
|
||||
public static final net.corda.core.transactions.TransactionBuilder move(net.corda.core.contracts.StateAndRef<net.corda.testing.contracts.DummyContract$SingleOwnerState>, net.corda.core.identity.AbstractParty)
|
||||
@NotNull
|
||||
public String toString()
|
||||
public void verify(net.corda.core.transactions.LedgerTransaction)
|
||||
public static final net.corda.testing.contracts.DummyContract$Companion Companion
|
||||
@NotNull
|
||||
public static final String PROGRAM_ID = "net.corda.testing.contracts.DummyContract"
|
||||
##
|
||||
public static interface net.corda.testing.contracts.DummyContract$Commands extends net.corda.core.contracts.CommandData
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContract$Commands$Create extends net.corda.core.contracts.TypeOnlyCommandData implements net.corda.testing.contracts.DummyContract$Commands
|
||||
public <init>()
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContract$Commands$Move extends net.corda.core.contracts.TypeOnlyCommandData implements net.corda.testing.contracts.DummyContract$Commands
|
||||
public <init>()
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContract$Companion extends java.lang.Object
|
||||
public <init>(kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
@NotNull
|
||||
public final net.corda.core.transactions.TransactionBuilder generateInitial(int, net.corda.core.identity.Party, net.corda.core.contracts.PartyAndReference, net.corda.core.contracts.PartyAndReference...)
|
||||
@NotNull
|
||||
public final net.corda.core.transactions.TransactionBuilder move(java.util.List<net.corda.core.contracts.StateAndRef<net.corda.testing.contracts.DummyContract$SingleOwnerState>>, net.corda.core.identity.AbstractParty)
|
||||
@NotNull
|
||||
public final net.corda.core.transactions.TransactionBuilder move(net.corda.core.contracts.StateAndRef<net.corda.testing.contracts.DummyContract$SingleOwnerState>, net.corda.core.identity.AbstractParty)
|
||||
##
|
||||
@DoNotImplement
|
||||
public static final class net.corda.testing.contracts.DummyContract$MultiOwnerState extends java.lang.Object implements net.corda.testing.contracts.DummyContract$State
|
||||
public <init>(int, java.util.List<? extends net.corda.core.identity.AbstractParty>)
|
||||
public <init>(int, java.util.List, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
public final int component1()
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.core.identity.AbstractParty> component2()
|
||||
@NotNull
|
||||
public final net.corda.testing.contracts.DummyContract$MultiOwnerState copy(int, java.util.List<? extends net.corda.core.identity.AbstractParty>)
|
||||
public boolean equals(Object)
|
||||
public int getMagicNumber()
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.core.identity.AbstractParty> getOwners()
|
||||
@NotNull
|
||||
public java.util.List<net.corda.core.identity.AbstractParty> getParticipants()
|
||||
public int hashCode()
|
||||
@NotNull
|
||||
public String toString()
|
||||
##
|
||||
@DoNotImplement
|
||||
public static final class net.corda.testing.contracts.DummyContract$SingleOwnerState extends java.lang.Object implements net.corda.core.contracts.OwnableState, net.corda.testing.contracts.DummyContract$State
|
||||
public <init>(int, net.corda.core.identity.AbstractParty)
|
||||
public <init>(int, net.corda.core.identity.AbstractParty, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
public final int component1()
|
||||
@NotNull
|
||||
public final net.corda.core.identity.AbstractParty component2()
|
||||
@NotNull
|
||||
public final net.corda.testing.contracts.DummyContract$SingleOwnerState copy(int, net.corda.core.identity.AbstractParty)
|
||||
public boolean equals(Object)
|
||||
public int getMagicNumber()
|
||||
@NotNull
|
||||
public net.corda.core.identity.AbstractParty getOwner()
|
||||
@NotNull
|
||||
public java.util.List<net.corda.core.identity.AbstractParty> getParticipants()
|
||||
public int hashCode()
|
||||
@NotNull
|
||||
public String toString()
|
||||
@NotNull
|
||||
public net.corda.core.contracts.CommandAndState withNewOwner(net.corda.core.identity.AbstractParty)
|
||||
##
|
||||
@DoNotImplement
|
||||
public static interface net.corda.testing.contracts.DummyContract$State extends net.corda.core.contracts.ContractState
|
||||
public abstract int getMagicNumber()
|
||||
##
|
||||
public final class net.corda.testing.contracts.DummyContractV2 extends java.lang.Object implements net.corda.core.contracts.UpgradedContractWithLegacyConstraint
|
||||
public <init>()
|
||||
@NotNull
|
||||
public String getLegacyContract()
|
||||
@NotNull
|
||||
public net.corda.core.contracts.AttachmentConstraint getLegacyContractConstraint()
|
||||
@NotNull
|
||||
public net.corda.testing.contracts.DummyContractV2$State upgrade(net.corda.testing.contracts.DummyContract$State)
|
||||
public void verify(net.corda.core.transactions.LedgerTransaction)
|
||||
public static final net.corda.testing.contracts.DummyContractV2$Companion Companion
|
||||
@NotNull
|
||||
public static final String PROGRAM_ID = "net.corda.testing.contracts.DummyContractV2"
|
||||
##
|
||||
public static interface net.corda.testing.contracts.DummyContractV2$Commands extends net.corda.core.contracts.CommandData
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContractV2$Commands$Create extends net.corda.core.contracts.TypeOnlyCommandData implements net.corda.testing.contracts.DummyContractV2$Commands
|
||||
public <init>()
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContractV2$Commands$Move extends net.corda.core.contracts.TypeOnlyCommandData implements net.corda.testing.contracts.DummyContractV2$Commands
|
||||
public <init>()
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContractV2$Companion extends java.lang.Object
|
||||
public <init>(kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContractV2$State extends java.lang.Object implements net.corda.core.contracts.ContractState
|
||||
public <init>(int, java.util.List<? extends net.corda.core.identity.AbstractParty>)
|
||||
public <init>(int, java.util.List, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
public final int component1()
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.core.identity.AbstractParty> component2()
|
||||
@NotNull
|
||||
public final net.corda.testing.contracts.DummyContractV2$State copy(int, java.util.List<? extends net.corda.core.identity.AbstractParty>)
|
||||
public boolean equals(Object)
|
||||
public final int getMagicNumber()
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.core.identity.AbstractParty> getOwners()
|
||||
@NotNull
|
||||
public java.util.List<net.corda.core.identity.AbstractParty> getParticipants()
|
||||
public int hashCode()
|
||||
@NotNull
|
||||
public String toString()
|
||||
##
|
||||
public final class net.corda.testing.contracts.DummyContractV3 extends java.lang.Object implements net.corda.core.contracts.UpgradedContractWithLegacyConstraint
|
||||
public <init>()
|
||||
@NotNull
|
||||
public String getLegacyContract()
|
||||
@NotNull
|
||||
public net.corda.core.contracts.AttachmentConstraint getLegacyContractConstraint()
|
||||
@NotNull
|
||||
public net.corda.testing.contracts.DummyContractV3$State upgrade(net.corda.testing.contracts.DummyContractV2$State)
|
||||
public void verify(net.corda.core.transactions.LedgerTransaction)
|
||||
public static final net.corda.testing.contracts.DummyContractV3$Companion Companion
|
||||
@NotNull
|
||||
public static final String PROGRAM_ID = "net.corda.testing.contracts.DummyContractV3"
|
||||
##
|
||||
public static interface net.corda.testing.contracts.DummyContractV3$Commands extends net.corda.core.contracts.CommandData
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContractV3$Commands$Create extends net.corda.core.contracts.TypeOnlyCommandData implements net.corda.testing.contracts.DummyContractV3$Commands
|
||||
public <init>()
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContractV3$Commands$Move extends net.corda.core.contracts.TypeOnlyCommandData implements net.corda.testing.contracts.DummyContractV3$Commands
|
||||
public <init>()
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContractV3$Companion extends java.lang.Object
|
||||
public <init>(kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
##
|
||||
public static final class net.corda.testing.contracts.DummyContractV3$State extends java.lang.Object implements net.corda.core.contracts.ContractState
|
||||
public <init>(int, java.util.List<? extends net.corda.core.identity.AbstractParty>)
|
||||
public <init>(int, java.util.List, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
public final int component1()
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.core.identity.AbstractParty> component2()
|
||||
@NotNull
|
||||
public final net.corda.testing.contracts.DummyContractV3$State copy(int, java.util.List<? extends net.corda.core.identity.AbstractParty>)
|
||||
public boolean equals(Object)
|
||||
public final int getMagicNumber()
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.core.identity.AbstractParty> getOwners()
|
||||
@NotNull
|
||||
public java.util.List<net.corda.core.identity.AbstractParty> getParticipants()
|
||||
public int hashCode()
|
||||
@NotNull
|
||||
public String toString()
|
||||
##
|
||||
@BelongsToContract
|
||||
public final class net.corda.testing.contracts.DummyState extends java.lang.Object implements net.corda.core.contracts.ContractState
|
||||
public <init>()
|
||||
public <init>(int)
|
||||
public <init>(int, java.util.List<? extends net.corda.core.identity.AbstractParty>)
|
||||
public <init>(int, java.util.List, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
public final int component1()
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.core.identity.AbstractParty> component2()
|
||||
@NotNull
|
||||
public final net.corda.testing.contracts.DummyState copy(int)
|
||||
@NotNull
|
||||
public final net.corda.testing.contracts.DummyState copy(int, java.util.List<? extends net.corda.core.identity.AbstractParty>)
|
||||
public boolean equals(Object)
|
||||
public final int getMagicNumber()
|
||||
@NotNull
|
||||
public java.util.List<net.corda.core.identity.AbstractParty> getParticipants()
|
||||
public int hashCode()
|
||||
@NotNull
|
||||
public String toString()
|
||||
##
|
||||
public final class net.corda.testing.core.DummyCommandData extends net.corda.core.contracts.TypeOnlyCommandData
|
||||
public static final net.corda.testing.core.DummyCommandData INSTANCE
|
||||
##
|
||||
public final class net.corda.testing.core.Expect extends java.lang.Object
|
||||
public <init>(Class<T>, kotlin.jvm.functions.Function1<? super T, Boolean>, kotlin.jvm.functions.Function1<? super T, kotlin.Unit>)
|
||||
@NotNull
|
||||
public final Class<T> component1()
|
||||
@NotNull
|
||||
public final kotlin.jvm.functions.Function1<T, Boolean> component2()
|
||||
@NotNull
|
||||
public final kotlin.jvm.functions.Function1<T, kotlin.Unit> component3()
|
||||
@NotNull
|
||||
public final net.corda.testing.core.Expect<E, T> copy(Class<T>, kotlin.jvm.functions.Function1<? super T, Boolean>, kotlin.jvm.functions.Function1<? super T, kotlin.Unit>)
|
||||
public boolean equals(Object)
|
||||
@NotNull
|
||||
public final Class<T> getClazz()
|
||||
@NotNull
|
||||
public final kotlin.jvm.functions.Function1<T, kotlin.Unit> getExpectClosure()
|
||||
@NotNull
|
||||
public final kotlin.jvm.functions.Function1<T, Boolean> getMatch()
|
||||
public int hashCode()
|
||||
@NotNull
|
||||
public String toString()
|
||||
##
|
||||
@DoNotImplement
|
||||
public abstract class net.corda.testing.core.ExpectCompose extends java.lang.Object
|
||||
public <init>(kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
##
|
||||
@DoNotImplement
|
||||
public static final class net.corda.testing.core.ExpectCompose$Parallel extends net.corda.testing.core.ExpectCompose
|
||||
public <init>(java.util.List<? extends net.corda.testing.core.ExpectCompose<? extends E>>)
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.testing.core.ExpectCompose<E>> getParallel()
|
||||
##
|
||||
@DoNotImplement
|
||||
public static final class net.corda.testing.core.ExpectCompose$Sequential extends net.corda.testing.core.ExpectCompose
|
||||
public <init>(java.util.List<? extends net.corda.testing.core.ExpectCompose<? extends E>>)
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.testing.core.ExpectCompose<E>> getSequence()
|
||||
##
|
||||
@DoNotImplement
|
||||
public static final class net.corda.testing.core.ExpectCompose$Single extends net.corda.testing.core.ExpectCompose
|
||||
public <init>(net.corda.testing.core.Expect<? extends E, T>)
|
||||
@NotNull
|
||||
public final net.corda.testing.core.Expect<E, T> getExpect()
|
||||
##
|
||||
public static final class net.corda.testing.core.ExpectComposeState$Companion extends java.lang.Object
|
||||
public <init>(kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
@NotNull
|
||||
public final net.corda.testing.core.ExpectComposeState<E> fromExpectCompose(net.corda.testing.core.ExpectCompose<? extends E>)
|
||||
##
|
||||
public static final class net.corda.testing.core.ExpectComposeState$Finished extends net.corda.testing.core.ExpectComposeState
|
||||
public <init>()
|
||||
@NotNull
|
||||
public java.util.List<Class<E>> getExpectedEvents()
|
||||
@Nullable
|
||||
public Void nextState(E)
|
||||
##
|
||||
public static final class net.corda.testing.core.ExpectComposeState$Parallel extends net.corda.testing.core.ExpectComposeState
|
||||
public <init>(net.corda.testing.core.ExpectCompose$Parallel<? extends E>, java.util.List<? extends net.corda.testing.core.ExpectComposeState<E>>)
|
||||
@NotNull
|
||||
public java.util.List<Class<? extends E>> getExpectedEvents()
|
||||
@NotNull
|
||||
public final net.corda.testing.core.ExpectCompose$Parallel<E> getParallel()
|
||||
@NotNull
|
||||
public final java.util.List<net.corda.testing.core.ExpectComposeState<E>> getStates()
|
||||
@Nullable
|
||||
public kotlin.Pair<kotlin.jvm.functions.Function0<kotlin.Unit>, net.corda.testing.core.ExpectComposeState<E>> nextState(E)
|
||||
##
|
||||
public static final class net.corda.testing.core.ExpectComposeState$Sequential extends net.corda.testing.core.ExpectComposeState
|
||||
public <init>(net.corda.testing.core.ExpectCompose$Sequential<? extends E>, int, net.corda.testing.core.ExpectComposeState<E>)
|
||||
@NotNull
|
||||
public java.util.List<Class<? extends E>> getExpectedEvents()
|
||||
public final int getIndex()
|
||||
@NotNull
|
||||
public final net.corda.testing.core.ExpectCompose$Sequential<E> getSequential()
|
||||
@NotNull
|
||||
public final net.corda.testing.core.ExpectComposeState<E> getState()
|
||||
@Nullable
|
||||
public kotlin.Pair<kotlin.jvm.functions.Function0<kotlin.Unit>, net.corda.testing.core.ExpectComposeState<E>> nextState(E)
|
||||
##
|
||||
public static final class net.corda.testing.core.ExpectComposeState$Single extends net.corda.testing.core.ExpectComposeState
|
||||
public <init>(net.corda.testing.core.ExpectCompose$Single<? extends E, T>)
|
||||
@NotNull
|
||||
public java.util.List<Class<T>> getExpectedEvents()
|
||||
@NotNull
|
||||
public final net.corda.testing.core.ExpectCompose$Single<E, T> getSingle()
|
||||
@Nullable
|
||||
public kotlin.Pair<kotlin.jvm.functions.Function0<kotlin.Unit>, net.corda.testing.core.ExpectComposeState<E>> nextState(E)
|
||||
##
|
||||
public final class net.corda.testing.core.ExpectKt extends java.lang.Object
|
||||
@NotNull
|
||||
public static final net.corda.testing.core.ExpectCompose<E> expect(Class<E>, kotlin.jvm.functions.Function1<? super E, Boolean>, kotlin.jvm.functions.Function1<? super E, kotlin.Unit>)
|
||||
public static final void expectEvents(Iterable<? extends E>, boolean, kotlin.jvm.functions.Function0<? extends net.corda.testing.core.ExpectCompose<? extends E>>)
|
||||
public static final void expectEvents(rx.Observable<E>, boolean, kotlin.jvm.functions.Function0<? extends net.corda.testing.core.ExpectCompose<? extends E>>)
|
||||
public static final void genericExpectEvents(S, boolean, kotlin.jvm.functions.Function2<? super S, ? super kotlin.jvm.functions.Function1<? super E, kotlin.Unit>, kotlin.Unit>, kotlin.jvm.functions.Function0<? extends net.corda.testing.core.ExpectCompose<? extends E>>)
|
||||
@NotNull
|
||||
public static final net.corda.testing.core.ExpectCompose<E> parallel(java.util.List<? extends net.corda.testing.core.ExpectCompose<? extends E>>)
|
||||
@NotNull
|
||||
public static final net.corda.testing.core.ExpectCompose<E> parallel(net.corda.testing.core.ExpectCompose<? extends E>...)
|
||||
@NotNull
|
||||
public static final net.corda.testing.core.ExpectCompose<E> replicate(int, kotlin.jvm.functions.Function1<? super Integer, ? extends net.corda.testing.core.ExpectCompose<? extends E>>)
|
||||
@NotNull
|
||||
public static final net.corda.testing.core.ExpectCompose<E> sequence(java.util.List<? extends net.corda.testing.core.ExpectCompose<? extends E>>)
|
||||
@NotNull
|
||||
public static final net.corda.testing.core.ExpectCompose<E> sequence(net.corda.testing.core.ExpectCompose<? extends E>...)
|
||||
##
|
||||
public final class net.corda.testing.core.SerializationEnvironmentRule extends java.lang.Object implements org.junit.rules.TestRule
|
||||
public <init>()
|
||||
public <init>(boolean)
|
||||
public <init>(boolean, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
@NotNull
|
||||
public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement, org.junit.runner.Description)
|
||||
@NotNull
|
||||
public final net.corda.core.serialization.SerializationFactory getSerializationFactory()
|
||||
public static final net.corda.testing.core.SerializationEnvironmentRule$Companion Companion
|
||||
##
|
||||
public static final class net.corda.testing.core.SerializationEnvironmentRule$Companion extends java.lang.Object
|
||||
public <init>(kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
##
|
||||
public final class net.corda.testing.core.TestConstants extends java.lang.Object
|
||||
@NotNull
|
||||
public static final net.corda.core.contracts.Command<net.corda.core.contracts.TypeOnlyCommandData> dummyCommand(java.security.PublicKey...)
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.CordaX500Name ALICE_NAME
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.CordaX500Name BOB_NAME
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.CordaX500Name BOC_NAME
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.CordaX500Name CHARLIE_NAME
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.CordaX500Name DUMMY_BANK_A_NAME
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.CordaX500Name DUMMY_BANK_B_NAME
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.CordaX500Name DUMMY_BANK_C_NAME
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.CordaX500Name DUMMY_NOTARY_NAME
|
||||
public static final int MAX_MESSAGE_SIZE = 10485760
|
||||
##
|
||||
public final class net.corda.testing.core.TestIdentity extends java.lang.Object
|
||||
public <init>(net.corda.core.identity.CordaX500Name)
|
||||
public <init>(net.corda.core.identity.CordaX500Name, long)
|
||||
public <init>(net.corda.core.identity.CordaX500Name, long, net.corda.core.crypto.SignatureScheme)
|
||||
public <init>(net.corda.core.identity.CordaX500Name, long, net.corda.core.crypto.SignatureScheme, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
public <init>(net.corda.core.identity.CordaX500Name, java.security.KeyPair)
|
||||
public <init>(net.corda.core.identity.CordaX500Name, net.corda.core.crypto.SignatureScheme)
|
||||
public <init>(net.corda.core.identity.CordaX500Name, net.corda.core.crypto.SignatureScheme, int, kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
@NotNull
|
||||
public static final net.corda.testing.core.TestIdentity fresh(String)
|
||||
@NotNull
|
||||
public static final net.corda.testing.core.TestIdentity fresh(String, net.corda.core.crypto.SignatureScheme)
|
||||
@NotNull
|
||||
public final net.corda.core.identity.PartyAndCertificate getIdentity()
|
||||
@NotNull
|
||||
public final java.security.KeyPair getKeyPair()
|
||||
@NotNull
|
||||
public final net.corda.core.identity.CordaX500Name getName()
|
||||
@NotNull
|
||||
public final net.corda.core.identity.Party getParty()
|
||||
@NotNull
|
||||
public final java.security.PublicKey getPublicKey()
|
||||
@NotNull
|
||||
public final net.corda.core.contracts.PartyAndReference ref(byte...)
|
||||
public static final net.corda.testing.core.TestIdentity$Companion Companion
|
||||
##
|
||||
public static final class net.corda.testing.core.TestIdentity$Companion extends java.lang.Object
|
||||
public <init>(kotlin.jvm.internal.DefaultConstructorMarker)
|
||||
@NotNull
|
||||
public final net.corda.testing.core.TestIdentity fresh(String)
|
||||
@NotNull
|
||||
public final net.corda.testing.core.TestIdentity fresh(String, net.corda.core.crypto.SignatureScheme)
|
||||
##
|
||||
public final class net.corda.testing.core.TestUtils extends java.lang.Object
|
||||
@NotNull
|
||||
public static final net.corda.core.utilities.NetworkHostAndPort freeLocalHostAndPort()
|
||||
public static final int freePort()
|
||||
@NotNull
|
||||
public static final net.corda.core.contracts.StateRef generateStateRef()
|
||||
@NotNull
|
||||
public static final java.util.List<net.corda.core.utilities.NetworkHostAndPort> getFreeLocalPorts(String, int)
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.PartyAndCertificate getTestPartyAndCertificate(net.corda.core.identity.CordaX500Name, java.security.PublicKey)
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.PartyAndCertificate getTestPartyAndCertificate(net.corda.core.identity.Party)
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.CordaX500Name makeUnique(net.corda.core.identity.CordaX500Name)
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.Party singleIdentity(net.corda.core.node.NodeInfo)
|
||||
@NotNull
|
||||
public static final net.corda.core.identity.PartyAndCertificate singleIdentityAndCert(net.corda.core.node.NodeInfo)
|
||||
##
|
||||
public final class net.corda.testing.dsl.AttachmentResolutionException extends net.corda.core.flows.FlowException
|
||||
public <init>(net.corda.core.crypto.SecureHash)
|
||||
##
|
||||
|
63
.ci/dev/nightly-regression/Jenkinsfile
vendored
63
.ci/dev/nightly-regression/Jenkinsfile
vendored
@ -23,34 +23,51 @@ pipeline {
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Generate Build Image') {
|
||||
steps {
|
||||
withCredentials([string(credentialsId: 'container_reg_passwd', variable: 'DOCKER_PUSH_PWD')]) {
|
||||
sh "./gradlew " +
|
||||
"-Dkubenetize=true " +
|
||||
"-Ddocker.push.password=\"\${DOCKER_PUSH_PWD}\" " +
|
||||
"-Ddocker.work.dir=\"/tmp/\${EXECUTOR_NUMBER}\" " +
|
||||
"-Ddocker.build.tag=\"\${DOCKER_TAG_TO_USE}\"" +
|
||||
" clean pushBuildImage --stacktrace"
|
||||
stage('Corda Pull Request - Generate Build Image') {
|
||||
steps {
|
||||
withCredentials([string(credentialsId: 'container_reg_passwd', variable: 'DOCKER_PUSH_PWD')]) {
|
||||
sh "./gradlew " +
|
||||
"-Dkubenetize=true " +
|
||||
"-Ddocker.push.password=\"\${DOCKER_PUSH_PWD}\" " +
|
||||
"-Ddocker.work.dir=\"/tmp/\${EXECUTOR_NUMBER}\" " +
|
||||
"-Ddocker.build.tag=\"\${DOCKER_TAG_TO_USE}\"" +
|
||||
" clean pushBuildImage --stacktrace"
|
||||
}
|
||||
sh "kubectl auth can-i get pods"
|
||||
}
|
||||
sh "kubectl auth can-i get pods"
|
||||
}
|
||||
}
|
||||
|
||||
stage('Regression Test') {
|
||||
steps {
|
||||
sh "./gradlew " +
|
||||
"-DbuildId=\"\${BUILD_ID}\" " +
|
||||
"-Dkubenetize=true " +
|
||||
"-Ddocker.run.tag=\"\${DOCKER_TAG_TO_USE}\" " +
|
||||
"-Dartifactory.username=\"\${ARTIFACTORY_CREDENTIALS_USR}\" " +
|
||||
"-Dartifactory.password=\"\${ARTIFACTORY_CREDENTIALS_PSW}\" " +
|
||||
"-Dgit.branch=\"\${GIT_BRANCH}\" " +
|
||||
"-Dgit.target.branch=\"\${GIT_BRANCH}\" " +
|
||||
" parallelRegressionTest --stacktrace"
|
||||
stage('Testing phase') {
|
||||
parallel {
|
||||
stage('Regression Test') {
|
||||
steps {
|
||||
sh "./gradlew " +
|
||||
"-DbuildId=\"\${BUILD_ID}\" " +
|
||||
"-Dkubenetize=true " +
|
||||
"-Ddocker.run.tag=\"\${DOCKER_TAG_TO_USE}\" " +
|
||||
"-Dartifactory.username=\"\${ARTIFACTORY_CREDENTIALS_USR}\" " +
|
||||
"-Dartifactory.password=\"\${ARTIFACTORY_CREDENTIALS_PSW}\" " +
|
||||
"-Dgit.branch=\"\${GIT_BRANCH}\" " +
|
||||
"-Dgit.target.branch=\"\${GIT_BRANCH}\" " +
|
||||
" parallelRegressionTest --stacktrace"
|
||||
}
|
||||
}
|
||||
stage('Slow Integration Test') {
|
||||
steps {
|
||||
sh "./gradlew " +
|
||||
"-DbuildId=\"\${BUILD_ID}\" " +
|
||||
"-Dkubenetize=true " +
|
||||
"-Ddocker.run.tag=\"\${DOCKER_TAG_TO_USE}\" " +
|
||||
"-Dartifactory.username=\"\${ARTIFACTORY_CREDENTIALS_USR}\" " +
|
||||
"-Dartifactory.password=\"\${ARTIFACTORY_CREDENTIALS_PSW}\" " +
|
||||
"-Dgit.branch=\"\${GIT_BRANCH}\" " +
|
||||
"-Dgit.target.branch=\"\${GIT_BRANCH}\" " +
|
||||
" allParallelSlowIntegrationTest --stacktrace"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
post {
|
||||
|
@ -1,4 +1,5 @@
|
||||
integration: { allParallelIntegrationTest }
|
||||
pr-merge: { parallelRegressionTest }
|
||||
smoke: { allParallelSmokeTest }
|
||||
slow: { allParallelSlowIntegrationTest }
|
||||
unit: { allParallelUnitTest }
|
||||
|
39
.ci/dev/regression/Jenkinsfile
vendored
39
.ci/dev/regression/Jenkinsfile
vendored
@ -33,17 +33,34 @@ pipeline {
|
||||
}
|
||||
}
|
||||
|
||||
stage('Regression Test') {
|
||||
steps {
|
||||
sh "./gradlew " +
|
||||
"-DbuildId=\"\${BUILD_ID}\" " +
|
||||
"-Dkubenetize=true " +
|
||||
"-Ddocker.run.tag=\"\${DOCKER_TAG_TO_USE}\" " +
|
||||
"-Dartifactory.username=\"\${ARTIFACTORY_CREDENTIALS_USR}\" " +
|
||||
"-Dartifactory.password=\"\${ARTIFACTORY_CREDENTIALS_PSW}\" " +
|
||||
"-Dgit.branch=\"\${GIT_BRANCH}\" " +
|
||||
"-Dgit.target.branch=\"\${GIT_BRANCH}\" " +
|
||||
" parallelRegressionTest --stacktrace"
|
||||
stage('Testing phase') {
|
||||
parallel {
|
||||
stage('Regression Test') {
|
||||
steps {
|
||||
sh "./gradlew " +
|
||||
"-DbuildId=\"\${BUILD_ID}\" " +
|
||||
"-Dkubenetize=true " +
|
||||
"-Ddocker.run.tag=\"\${DOCKER_TAG_TO_USE}\" " +
|
||||
"-Dartifactory.username=\"\${ARTIFACTORY_CREDENTIALS_USR}\" " +
|
||||
"-Dartifactory.password=\"\${ARTIFACTORY_CREDENTIALS_PSW}\" " +
|
||||
"-Dgit.branch=\"\${GIT_BRANCH}\" " +
|
||||
"-Dgit.target.branch=\"\${GIT_BRANCH}\" " +
|
||||
" parallelRegressionTest --stacktrace"
|
||||
}
|
||||
}
|
||||
stage('Slow Integration Test') {
|
||||
steps {
|
||||
sh "./gradlew " +
|
||||
"-DbuildId=\"\${BUILD_ID}\" " +
|
||||
"-Dkubenetize=true " +
|
||||
"-Ddocker.run.tag=\"\${DOCKER_TAG_TO_USE}\" " +
|
||||
"-Dartifactory.username=\"\${ARTIFACTORY_CREDENTIALS_USR}\" " +
|
||||
"-Dartifactory.password=\"\${ARTIFACTORY_CREDENTIALS_PSW}\" " +
|
||||
"-Dgit.branch=\"\${GIT_BRANCH}\" " +
|
||||
"-Dgit.target.branch=\"\${GIT_BRANCH}\" " +
|
||||
" allParallelSlowIntegrationTest --stacktrace"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
4
Jenkinsfile
vendored
4
Jenkinsfile
vendored
@ -45,6 +45,8 @@ pipeline {
|
||||
"-Dartifactory.password=\"\${ARTIFACTORY_CREDENTIALS_PSW}\" " +
|
||||
"-Dgit.branch=\"\${GIT_BRANCH}\" " +
|
||||
"-Dgit.target.branch=\"\${CHANGE_TARGET}\" " +
|
||||
"-Ddependx.branch.origin=${env.GIT_COMMIT} " +
|
||||
"-Ddependx.branch.target=${CHANGE_TARGET} " +
|
||||
" allParallelIntegrationTest --stacktrace"
|
||||
}
|
||||
}
|
||||
@ -58,6 +60,8 @@ pipeline {
|
||||
"-Dartifactory.password=\"\${ARTIFACTORY_CREDENTIALS_PSW}\" " +
|
||||
"-Dgit.branch=\"\${GIT_BRANCH}\" " +
|
||||
"-Dgit.target.branch=\"\${CHANGE_TARGET}\" " +
|
||||
"-Ddependx.branch.origin=${env.GIT_COMMIT} " +
|
||||
"-Ddependx.branch.target=${CHANGE_TARGET} " +
|
||||
" allParallelUnitTest --stacktrace"
|
||||
}
|
||||
}
|
||||
|
77
build.gradle
77
build.gradle
@ -25,14 +25,14 @@ buildscript {
|
||||
|
||||
ext.quasar_group = 'co.paralleluniverse'
|
||||
// Set version of Quasar according to version of Java used:
|
||||
if (JavaVersion.current() == JavaVersion.VERSION_11) {
|
||||
ext.quasar_version = constants.getProperty("quasarVersion11")
|
||||
ext.quasar_classifier = constants.getProperty("quasarClassifier11")
|
||||
ext.jdkClassifier = constants.getProperty("jdkClassifier11")
|
||||
} else {
|
||||
if (JavaVersion.current().isJava8()) {
|
||||
ext.quasar_version = constants.getProperty("quasarVersion")
|
||||
ext.quasar_classifier = constants.getProperty("quasarClassifier")
|
||||
ext.jdkClassifier = constants.getProperty("jdkClassifier")
|
||||
} else {
|
||||
ext.quasar_version = constants.getProperty("quasarVersion11")
|
||||
ext.quasar_classifier = constants.getProperty("quasarClassifier11")
|
||||
ext.jdkClassifier = constants.getProperty("jdkClassifier11")
|
||||
}
|
||||
ext.cordaScanApiClassifier = jdkClassifier
|
||||
ext.quasar_exclusions = [
|
||||
@ -83,6 +83,8 @@ buildscript {
|
||||
ext.tcnative_version = '2.0.14.Final'
|
||||
ext.typesafe_config_version = constants.getProperty("typesafeConfigVersion")
|
||||
ext.fileupload_version = '1.4'
|
||||
ext.kryo_version = '4.0.2'
|
||||
ext.kryo_serializer_version = '0.43'
|
||||
// Legacy JUnit 4 version
|
||||
ext.junit_version = '4.12'
|
||||
// Need this version to access classpath scanning error handling fix -
|
||||
@ -104,7 +106,7 @@ buildscript {
|
||||
ext.dependency_checker_version = '5.2.0'
|
||||
ext.commons_collections_version = '4.3'
|
||||
ext.beanutils_version = '1.9.3'
|
||||
ext.crash_version = '1.7.2'
|
||||
ext.crash_version = '1.7.4'
|
||||
ext.jsr305_version = constants.getProperty("jsr305Version")
|
||||
ext.shiro_version = '1.4.1'
|
||||
ext.artifactory_plugin_version = constants.getProperty('artifactoryPluginVersion')
|
||||
@ -125,13 +127,14 @@ buildscript {
|
||||
ext.commons_lang_version = '3.9'
|
||||
ext.commons_io_version = '2.6'
|
||||
ext.controlsfx_version = '8.40.15'
|
||||
if (JavaVersion.current() == JavaVersion.VERSION_11) {
|
||||
ext.detekt_version = constants.getProperty('detektVersion')
|
||||
if (JavaVersion.current().isJava8()) {
|
||||
ext.fontawesomefx_commons_version = '8.15'
|
||||
ext.fontawesomefx_fontawesome_version = '4.7.0-5'
|
||||
} else {
|
||||
// has been compiled by a more recent version of the Java Runtime (class file version 55.0)
|
||||
ext.fontawesomefx_commons_version = '11.0'
|
||||
ext.fontawesomefx_fontawesome_version = '4.7.0-11'
|
||||
} else {
|
||||
ext.fontawesomefx_commons_version = '8.15'
|
||||
ext.fontawesomefx_fontawesome_version = '4.7.0-5'
|
||||
}
|
||||
|
||||
// Name of the IntelliJ SDK created for the deterministic Java rt.jar.
|
||||
@ -184,6 +187,7 @@ buildscript {
|
||||
// See https://github.com/corda/gradle-capsule-plugin
|
||||
classpath "us.kirchmeier:gradle-capsule-plugin:1.0.4_r3"
|
||||
classpath group: "com.r3.testing", name: "gradle-distributed-testing-plugin", version: "1.2-LOCAL-K8S-SHARED-CACHE-SNAPSHOT", changing: true
|
||||
classpath group: "com.r3.dependx", name: "gradle-dependx", version: "0.1.12", changing: true
|
||||
classpath "com.bmuschko:gradle-docker-plugin:5.0.0"
|
||||
}
|
||||
}
|
||||
@ -201,6 +205,7 @@ apply plugin: 'net.corda.plugins.publish-utils'
|
||||
apply plugin: 'maven-publish'
|
||||
apply plugin: 'com.jfrog.artifactory'
|
||||
apply plugin: "com.bmuschko.docker-remote-api"
|
||||
apply plugin: "com.r3.dependx.dependxies"
|
||||
|
||||
|
||||
// If the command line project option -PversionFromGit is added to the gradle invocation, we'll resolve
|
||||
@ -224,11 +229,7 @@ apply plugin: 'java'
|
||||
|
||||
logger.lifecycle("Java version: {}", JavaVersion.current())
|
||||
sourceCompatibility = VERSION_1_8
|
||||
if (JavaVersion.current() == JavaVersion.VERSION_1_8) {
|
||||
targetCompatibility = VERSION_1_8
|
||||
} else {
|
||||
targetCompatibility = VERSION_11
|
||||
}
|
||||
targetCompatibility = JavaVersion.current().isJava8() ? VERSION_1_8 : VERSION_11
|
||||
logger.lifecycle("Java source compatibility: {}", sourceCompatibility)
|
||||
logger.lifecycle("Java target compatibility: {}", targetCompatibility)
|
||||
logger.lifecycle("Quasar version: {}", quasar_version)
|
||||
@ -264,11 +265,7 @@ allprojects {
|
||||
}
|
||||
}
|
||||
sourceCompatibility = VERSION_1_8
|
||||
if (JavaVersion.current() == JavaVersion.VERSION_1_8) {
|
||||
targetCompatibility = VERSION_1_8
|
||||
} else {
|
||||
targetCompatibility = VERSION_11
|
||||
}
|
||||
targetCompatibility = JavaVersion.current().isJava8() ? VERSION_1_8 : VERSION_11
|
||||
|
||||
jacoco {
|
||||
// JDK11 official support (https://github.com/jacoco/jacoco/releases/tag/v0.8.3)
|
||||
@ -291,7 +288,7 @@ allprojects {
|
||||
kotlinOptions {
|
||||
languageVersion = "1.2"
|
||||
apiVersion = "1.2"
|
||||
jvmTarget = "1.8"
|
||||
jvmTarget = VERSION_1_8
|
||||
javaParameters = true // Useful for reflection.
|
||||
freeCompilerArgs = ['-Xjvm-default=compatibility']
|
||||
allWarningsAsErrors = warnings_as_errors
|
||||
@ -464,17 +461,20 @@ task jacocoRootReport(type: org.gradle.testing.jacoco.tasks.JacocoReport) {
|
||||
}
|
||||
}
|
||||
|
||||
task detekt(type: JavaExec) {
|
||||
main = "io.gitlab.arturbosch.detekt.cli.Main"
|
||||
classpath = configurations.detekt
|
||||
tasks.register('detekt', JavaExec) {
|
||||
def input = "$projectDir"
|
||||
def config = "$projectDir/detekt-config.yml"
|
||||
def baseline = "$projectDir/detekt-baseline.xml"
|
||||
def params = ['-i', input, '-c', config, '-b', baseline]
|
||||
def detektPluginsJar = project(':detekt-plugins').tasks.jar
|
||||
def plugins = detektPluginsJar.outputs.files.singleFile
|
||||
def params = ['-i', input, '-c', config, '-b', baseline, '--plugins', plugins]
|
||||
inputs.files(detektPluginsJar, config, baseline)
|
||||
main = "io.gitlab.arturbosch.detekt.cli.Main"
|
||||
classpath = configurations.detekt
|
||||
args(params)
|
||||
}
|
||||
|
||||
task detektBaseline(type: JavaExec) {
|
||||
tasks.register('detektBaseline', JavaExec) {
|
||||
main = "io.gitlab.arturbosch.detekt.cli.Main"
|
||||
classpath = configurations.detekt
|
||||
def input = "$projectDir"
|
||||
@ -519,6 +519,7 @@ bintrayConfig {
|
||||
'corda-node-api',
|
||||
'corda-node-djvm',
|
||||
'corda-test-common',
|
||||
'corda-core-test-utils',
|
||||
'corda-test-utils',
|
||||
'corda-test-db',
|
||||
'corda-jackson',
|
||||
@ -584,6 +585,11 @@ artifactory {
|
||||
}
|
||||
}
|
||||
|
||||
dependxiesModule {
|
||||
mode = "monitor"
|
||||
skipTasks = "test,integrationTest,smokeTest,slowIntegrationTest"
|
||||
}
|
||||
|
||||
task generateApi(type: net.corda.plugins.GenerateApi) {
|
||||
baseName = "api-corda"
|
||||
}
|
||||
@ -630,6 +636,7 @@ buildScan {
|
||||
}
|
||||
|
||||
task allParallelIntegrationTest(type: ParallelTestGroup) {
|
||||
dependsOn dependxiesModule
|
||||
podLogLevel PodLogLevel.INFO
|
||||
testGroups "integrationTest"
|
||||
numberOfShards 10
|
||||
@ -640,6 +647,7 @@ task allParallelIntegrationTest(type: ParallelTestGroup) {
|
||||
nodeTaints "big"
|
||||
}
|
||||
task allParallelUnitTest(type: ParallelTestGroup) {
|
||||
dependsOn dependxiesModule
|
||||
podLogLevel PodLogLevel.INFO
|
||||
testGroups "test"
|
||||
numberOfShards 10
|
||||
@ -650,6 +658,7 @@ task allParallelUnitTest(type: ParallelTestGroup) {
|
||||
nodeTaints "small"
|
||||
}
|
||||
task allParallelUnitAndIntegrationTest(type: ParallelTestGroup) {
|
||||
dependsOn dependxiesModule
|
||||
testGroups "test", "integrationTest"
|
||||
numberOfShards 15
|
||||
streamOutput false
|
||||
@ -659,7 +668,8 @@ task allParallelUnitAndIntegrationTest(type: ParallelTestGroup) {
|
||||
nodeTaints "big"
|
||||
}
|
||||
task parallelRegressionTest(type: ParallelTestGroup) {
|
||||
testGroups "test", "integrationTest", "slowIntegrationTest", "smokeTest"
|
||||
testGroups "test", "integrationTest", "smokeTest"
|
||||
dependsOn dependxiesModule
|
||||
numberOfShards 15
|
||||
streamOutput false
|
||||
coresPerFork 2
|
||||
@ -668,7 +678,18 @@ task parallelRegressionTest(type: ParallelTestGroup) {
|
||||
nodeTaints "big"
|
||||
}
|
||||
task allParallelSmokeTest(type: ParallelTestGroup) {
|
||||
testGroups "slowIntegrationTest", "smokeTest"
|
||||
testGroups "smokeTest"
|
||||
dependsOn dependxiesModule
|
||||
numberOfShards 4
|
||||
streamOutput false
|
||||
coresPerFork 6
|
||||
memoryInGbPerFork 10
|
||||
distribute DistributeTestsBy.CLASS
|
||||
nodeTaints "big"
|
||||
}
|
||||
task allParallelSlowIntegrationTest(type: ParallelTestGroup) {
|
||||
testGroups "slowIntegrationTest"
|
||||
dependsOn dependxiesModule
|
||||
numberOfShards 4
|
||||
streamOutput false
|
||||
coresPerFork 6
|
||||
|
@ -42,8 +42,8 @@ import net.corda.nodeapi.internal.crypto.x509Certificates
|
||||
import net.corda.testing.common.internal.testNetworkParameters
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.core.*
|
||||
import net.corda.testing.internal.createNodeInfoAndSigned
|
||||
import net.corda.testing.internal.rigorousMock
|
||||
import net.corda.coretesting.internal.createNodeInfoAndSigned
|
||||
import net.corda.coretesting.internal.rigorousMock
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.junit.Before
|
||||
|
@ -29,7 +29,13 @@ dependencies {
|
||||
jar {
|
||||
baseName 'corda-mock'
|
||||
manifest {
|
||||
attributes 'Automatic-Module-Name': 'net.corda.client.mock'
|
||||
attributes(
|
||||
'Automatic-Module-Name': 'net.corda.client.mock',
|
||||
|
||||
// This JAR is part of Corda's testing framework.
|
||||
// Driver will not include it as part of an out-of-process node.
|
||||
'Corda-Testing': true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,9 @@ sourceSets {
|
||||
runtimeClasspath += main.output + test.output
|
||||
srcDir file('src/integration-test/java')
|
||||
}
|
||||
resources {
|
||||
srcDirs "src/integration-test/resources"
|
||||
}
|
||||
}
|
||||
smokeTest {
|
||||
kotlin {
|
||||
@ -100,7 +103,7 @@ dependencies {
|
||||
smokeTestRuntimeOnly "org.junit.platform:junit-platform-launcher:${junit_platform_version}"
|
||||
|
||||
// JDK11: required by Quasar at run-time
|
||||
smokeTestRuntimeOnly "com.esotericsoftware:kryo:4.0.2"
|
||||
smokeTestRuntimeOnly "com.esotericsoftware:kryo:$kryo_version"
|
||||
}
|
||||
|
||||
task integrationTest(type: Test) {
|
||||
|
@ -1,13 +1,22 @@
|
||||
package net.corda.client.rpc
|
||||
|
||||
import net.corda.core.context.*
|
||||
import net.corda.core.CordaRuntimeException
|
||||
import net.corda.core.context.Actor
|
||||
import net.corda.core.context.AuthServiceId
|
||||
import net.corda.core.context.InvocationContext
|
||||
import net.corda.core.context.InvocationOrigin
|
||||
import net.corda.core.context.Trace
|
||||
import net.corda.core.contracts.FungibleAsset
|
||||
import net.corda.core.crypto.random63BitValue
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.concurrent.flatMap
|
||||
import net.corda.core.internal.location
|
||||
import net.corda.core.internal.toPath
|
||||
import net.corda.core.messaging.*
|
||||
import net.corda.core.messaging.FlowProgressHandle
|
||||
import net.corda.core.messaging.StateMachineInfo
|
||||
import net.corda.core.messaging.StateMachineUpdate
|
||||
import net.corda.core.messaging.startFlow
|
||||
import net.corda.core.messaging.startTrackedFlow
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.core.utilities.OpaqueBytes
|
||||
import net.corda.core.utilities.contextLogger
|
||||
@ -22,8 +31,14 @@ import net.corda.finance.workflows.getCashBalance
|
||||
import net.corda.finance.workflows.getCashBalances
|
||||
import net.corda.node.internal.NodeWithInfo
|
||||
import net.corda.node.services.Permissions.Companion.all
|
||||
import net.corda.nodeapi.exceptions.DuplicateAttachmentException
|
||||
import net.corda.testing.common.internal.checkNotOnClasspath
|
||||
import net.corda.testing.core.*
|
||||
import net.corda.testing.core.ALICE_NAME
|
||||
import net.corda.testing.core.BOB_NAME
|
||||
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
||||
import net.corda.testing.core.expect
|
||||
import net.corda.testing.core.expectEvents
|
||||
import net.corda.testing.core.sequence
|
||||
import net.corda.testing.node.User
|
||||
import net.corda.testing.node.internal.NodeBasedTest
|
||||
import net.corda.testing.node.internal.ProcessUtilities
|
||||
@ -31,6 +46,7 @@ import net.corda.testing.node.internal.poll
|
||||
import org.apache.activemq.artemis.api.core.ActiveMQSecurityException
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatExceptionOfType
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
@ -38,7 +54,10 @@ import rx.subjects.PublishSubject
|
||||
import java.net.URLClassLoader
|
||||
import java.nio.file.Paths
|
||||
import java.util.*
|
||||
import java.util.concurrent.*
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.ScheduledExecutorService
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
@ -47,6 +66,7 @@ class CordaRPCClientTest : NodeBasedTest(listOf("net.corda.finance"), notaries =
|
||||
companion object {
|
||||
val rpcUser = User("user1", "test", permissions = setOf(all()))
|
||||
val log = contextLogger()
|
||||
const val testJar = "net/corda/client/rpc/test.jar"
|
||||
}
|
||||
|
||||
private lateinit var node: NodeWithInfo
|
||||
@ -244,6 +264,29 @@ class CordaRPCClientTest : NodeBasedTest(listOf("net.corda.finance"), notaries =
|
||||
assertThat(outOfProcessRpc.waitFor()).isZero() // i.e. no exceptions were thrown
|
||||
}
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun `nonspecific reconnect errors dont trigger graceful reconnect`() {
|
||||
val inputJar1 = Thread.currentThread().contextClassLoader.getResourceAsStream(testJar)!!
|
||||
val inputJar2 = Thread.currentThread().contextClassLoader.getResourceAsStream(testJar)!!
|
||||
var disconnects = 0
|
||||
var reconnects = 0
|
||||
val gracefulReconnect = GracefulReconnect(onDisconnect = {++disconnects}, onReconnect = {++reconnects})
|
||||
|
||||
// This just recreates the original issue which allowed us to fix this. Any non-rpc exception would do
|
||||
// https://r3-cev.atlassian.net/browse/CORDA-3572
|
||||
assertThatThrownBy {
|
||||
client.start(rpcUser.username, rpcUser.password, gracefulReconnect = gracefulReconnect).use {
|
||||
val rpc = it.proxy
|
||||
rpc.uploadAttachment(inputJar1)
|
||||
rpc.uploadAttachment(inputJar2)
|
||||
}
|
||||
}.isInstanceOf(CordaRuntimeException::class.java)
|
||||
.hasMessageContaining(DuplicateAttachmentException::class.java.name)
|
||||
|
||||
assertThat(disconnects).isEqualTo(0)
|
||||
assertThat(reconnects).isEqualTo(0)
|
||||
}
|
||||
|
||||
private fun checkShellNotification(info: StateMachineInfo) {
|
||||
val context = info.invocationContext
|
||||
assertThat(context.origin).isInstanceOf(InvocationOrigin.Shell::class.java)
|
||||
|
@ -20,7 +20,7 @@ import net.corda.testing.common.internal.eventually
|
||||
import net.corda.testing.common.internal.succeeds
|
||||
import net.corda.testing.core.SerializationEnvironmentRule
|
||||
import net.corda.testing.driver.internal.incrementalPortAllocation
|
||||
import net.corda.testing.internal.testThreadFactory
|
||||
import net.corda.coretesting.internal.testThreadFactory
|
||||
import net.corda.testing.node.internal.RPCDriverDSL
|
||||
import net.corda.testing.node.internal.RpcBrokerHandle
|
||||
import net.corda.testing.node.internal.RpcServerHandle
|
||||
|
@ -72,7 +72,7 @@ class RpcCustomSerializersTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(timeout=300_000)
|
||||
fun `when a custom serializer is missing from the rpc client the resulting exception progagtes and client does not reconnect`() {
|
||||
driver(DriverParameters(startNodesInProcess = false, cordappsForAllNodes = listOf(enclosedCordapp()))) {
|
||||
val server = startNode(providedName = ALICE_NAME).get()
|
||||
|
@ -26,6 +26,7 @@ import net.corda.testing.node.internal.rpcDriver
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.junit.Test
|
||||
import java.lang.RuntimeException
|
||||
import java.lang.Thread.sleep
|
||||
import java.time.Duration
|
||||
import java.util.concurrent.CountDownLatch
|
||||
@ -163,6 +164,47 @@ class CordaRPCClientReconnectionTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun `when user code throws an error on a reconnecting observable, then onError is invoked and observable is unsubscribed successfully`() {
|
||||
driver(DriverParameters(cordappsForAllNodes = FINANCE_CORDAPPS)) {
|
||||
val normalLatch = CountDownLatch(1)
|
||||
val errorLatch = CountDownLatch(1)
|
||||
var observedEvents = 0
|
||||
|
||||
fun startNode(address: NetworkHostAndPort): NodeHandle {
|
||||
return startNode(
|
||||
providedName = CHARLIE_NAME,
|
||||
rpcUsers = listOf(CordaRPCClientTest.rpcUser),
|
||||
customOverrides = mapOf("rpcSettings.address" to address.toString())
|
||||
).getOrThrow()
|
||||
}
|
||||
|
||||
val addresses = listOf(NetworkHostAndPort("localhost", portAllocator.nextPort()), NetworkHostAndPort("localhost", portAllocator.nextPort()))
|
||||
|
||||
startNode(addresses[0])
|
||||
val client = CordaRPCClient(addresses)
|
||||
|
||||
(client.start(rpcUser.username, rpcUser.password, gracefulReconnect = gracefulReconnect)).use {
|
||||
val rpcOps = it.proxy as ReconnectingCordaRPCOps
|
||||
val cashStatesFeed = rpcOps.vaultTrack(Cash.State::class.java)
|
||||
val subscription = cashStatesFeed.updates.subscribe ({
|
||||
normalLatch.countDown()
|
||||
observedEvents++
|
||||
throw RuntimeException()
|
||||
}, {
|
||||
errorLatch.countDown()
|
||||
})
|
||||
rpcOps.startTrackedFlow(::CashIssueFlow, 10.DOLLARS, OpaqueBytes.of(0), defaultNotaryIdentity).returnValue.get()
|
||||
rpcOps.startTrackedFlow(::CashIssueFlow, 10.DOLLARS, OpaqueBytes.of(0), defaultNotaryIdentity).returnValue.get()
|
||||
|
||||
assertTrue { normalLatch.await(2, TimeUnit.SECONDS) }
|
||||
assertTrue { errorLatch.await(2, TimeUnit.SECONDS) }
|
||||
assertThat(subscription.isUnsubscribed).isTrue()
|
||||
assertThat(observedEvents).isEqualTo(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun `an RPC call fails, when the maximum number of attempts is exceeded`() {
|
||||
driver(DriverParameters(cordappsForAllNodes = emptyList())) {
|
||||
|
Binary file not shown.
@ -3,7 +3,7 @@ package net.corda.client.rpc
|
||||
import com.github.benmanes.caffeine.cache.Caffeine
|
||||
import net.corda.client.rpc.internal.RPCClient
|
||||
import net.corda.client.rpc.internal.ReconnectingCordaRPCOps
|
||||
import net.corda.client.rpc.internal.serialization.amqp.AMQPClientSerializationScheme
|
||||
import net.corda.nodeapi.internal.rpc.client.AMQPClientSerializationScheme
|
||||
import net.corda.client.rpc.reconnect.CouldNotStartFlowException
|
||||
import net.corda.core.CordaInternal
|
||||
import net.corda.core.context.Actor
|
||||
|
@ -1,6 +1,5 @@
|
||||
package net.corda.client.rpc.internal
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache
|
||||
import com.github.benmanes.caffeine.cache.Caffeine
|
||||
import com.github.benmanes.caffeine.cache.RemovalCause
|
||||
import com.github.benmanes.caffeine.cache.RemovalListener
|
||||
@ -11,7 +10,7 @@ import net.corda.client.rpc.ConnectionFailureException
|
||||
import net.corda.client.rpc.CordaRPCClientConfiguration
|
||||
import net.corda.client.rpc.RPCException
|
||||
import net.corda.client.rpc.RPCSinceVersion
|
||||
import net.corda.client.rpc.internal.serialization.amqp.RpcClientObservableDeSerializer
|
||||
import net.corda.nodeapi.internal.rpc.client.RpcClientObservableDeSerializer
|
||||
import net.corda.core.context.Actor
|
||||
import net.corda.core.context.Trace
|
||||
import net.corda.core.context.Trace.InvocationId
|
||||
@ -33,6 +32,10 @@ import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.nodeapi.RPCApi
|
||||
import net.corda.nodeapi.RPCApi.CLASS_METHOD_DIVIDER
|
||||
import net.corda.nodeapi.internal.DeduplicationChecker
|
||||
import net.corda.nodeapi.internal.rpc.client.CallSite
|
||||
import net.corda.nodeapi.internal.rpc.client.CallSiteMap
|
||||
import net.corda.nodeapi.internal.rpc.client.ObservableContext
|
||||
import net.corda.nodeapi.internal.rpc.client.RpcObservableMap
|
||||
import org.apache.activemq.artemis.api.core.ActiveMQException
|
||||
import org.apache.activemq.artemis.api.core.ActiveMQNotConnectedException
|
||||
import org.apache.activemq.artemis.api.core.RoutingType
|
||||
@ -257,9 +260,6 @@ class RPCClientProxyHandler(
|
||||
startSessions()
|
||||
}
|
||||
|
||||
/** A throwable that doesn't represent a real error - it's just here to wrap a stack trace. */
|
||||
class CallSite(val rpcName: String) : Throwable("<Call site of root RPC '$rpcName'>")
|
||||
|
||||
// This is the general function that transforms a client side RPC to internal Artemis messages.
|
||||
override fun invoke(proxy: Any, method: Method, arguments: Array<out Any?>?): Any? {
|
||||
lifeCycle.requireState { it == State.STARTED || it == State.SERVER_VERSION_NOT_SET }
|
||||
@ -666,20 +666,5 @@ class RPCClientProxyHandler(
|
||||
}
|
||||
}
|
||||
|
||||
private typealias RpcObservableMap = Cache<InvocationId, UnicastSubject<Notification<*>>>
|
||||
private typealias RpcReplyMap = ConcurrentHashMap<InvocationId, SettableFuture<Any?>>
|
||||
private typealias CallSiteMap = ConcurrentHashMap<InvocationId, RPCClientProxyHandler.CallSite?>
|
||||
|
||||
/**
|
||||
* Holds a context available during de-serialisation of messages that are expected to contain Observables.
|
||||
*
|
||||
* @property observableMap holds the Observables that are ultimately exposed to the user.
|
||||
* @property hardReferenceStore holds references to Observables we want to keep alive while they are subscribed to.
|
||||
* @property callSiteMap keeps stack traces captured when an RPC was invoked, useful for debugging when an observable leaks.
|
||||
*/
|
||||
data class ObservableContext(
|
||||
val callSiteMap: CallSiteMap?,
|
||||
val observableMap: RpcObservableMap,
|
||||
val hardReferenceStore: MutableSet<Observable<*>>
|
||||
)
|
||||
private typealias RpcReplyMap = ConcurrentHashMap<Trace.InvocationId, SettableFuture<Any?>>
|
||||
|
||||
|
@ -17,6 +17,7 @@ import net.corda.client.rpc.internal.ReconnectingCordaRPCOps.ReconnectingRPCConn
|
||||
import net.corda.client.rpc.reconnect.CouldNotStartFlowException
|
||||
import net.corda.core.flows.StateMachineRunId
|
||||
import net.corda.core.internal.messaging.InternalCordaRPCOps
|
||||
import net.corda.core.internal.min
|
||||
import net.corda.core.internal.times
|
||||
import net.corda.core.internal.uncheckedCast
|
||||
import net.corda.core.messaging.ClientRpcSslOptions
|
||||
@ -262,11 +263,15 @@ class ReconnectingCordaRPCOps private constructor(
|
||||
}
|
||||
// Could not connect this time round - pause before giving another try.
|
||||
Thread.sleep(retryInterval.toMillis())
|
||||
// TODO - make the exponential retry factor configurable.
|
||||
val nextRoundRobinIndex = (roundRobinIndex + 1) % nodeHostAndPorts.size
|
||||
val nextInterval = retryInterval * rpcConfiguration.connectionRetryIntervalMultiplier
|
||||
val nextInterval = min(
|
||||
rpcConfiguration.connectionMaxRetryInterval,
|
||||
retryInterval * rpcConfiguration.connectionRetryIntervalMultiplier
|
||||
)
|
||||
log.info("Could not establish connection. Next retry interval $nextInterval")
|
||||
return establishConnectionWithRetry(nextInterval, nextRoundRobinIndex, remainingRetries)
|
||||
}
|
||||
|
||||
override val proxy: CordaRPCOps
|
||||
get() = current.proxy
|
||||
override val serverProtocolVersion
|
||||
@ -301,6 +306,7 @@ class ReconnectingCordaRPCOps private constructor(
|
||||
*
|
||||
* A negative number for [maxNumberOfAttempts] means an unlimited number of retries will be performed.
|
||||
*/
|
||||
@Suppress("ThrowsCount", "ComplexMethod")
|
||||
private fun doInvoke(method: Method, args: Array<out Any>?, maxNumberOfAttempts: Int): Any? {
|
||||
checkIfClosed()
|
||||
var remainingAttempts = maxNumberOfAttempts
|
||||
@ -334,9 +340,8 @@ class ReconnectingCordaRPCOps private constructor(
|
||||
throw RPCException("User does not have permission to perform operation ${method.name}.", e)
|
||||
}
|
||||
else -> {
|
||||
log.warn("Failed to perform operation ${method.name}. Unknown error. Retrying....", e)
|
||||
reconnectingRPCConnection.reconnectOnError(e)
|
||||
checkIfIsStartFlow(method, e)
|
||||
log.warn("Failed to perform operation ${method.name}.", e)
|
||||
throw e.targetException
|
||||
}
|
||||
}
|
||||
lastException = e.targetException
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.corda.client.rpc.internal
|
||||
|
||||
import net.corda.client.rpc.ConnectionFailureException
|
||||
import net.corda.core.messaging.DataFeed
|
||||
import rx.Observable
|
||||
import rx.Subscriber
|
||||
@ -54,16 +55,30 @@ class ReconnectingObservable<T> private constructor(subscriber: ReconnectingSubs
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Depending on the type of error, the reaction is different:
|
||||
* - If the error is coming from a connection disruption, we establish a new connection and re-wire the observable
|
||||
* without letting the client notice at all.
|
||||
* - In any other case, we let the error propagate to the client's observable. Both of the observables
|
||||
* (this one and the client's one) will be automatically unsubscribed, since that's the semantics of onError.
|
||||
*/
|
||||
private fun scheduleResubscribe(error: Throwable) {
|
||||
if (unsubscribed) return
|
||||
reconnectingRPCConnection.observersPool.execute {
|
||||
if (unsubscribed || reconnectingRPCConnection.isClosed()) return@execute
|
||||
reconnectingRPCConnection.reconnectOnError(error)
|
||||
// It can take a while to reconnect so we might find that we've shutdown in in the meantime
|
||||
if (unsubscribed || reconnectingRPCConnection.isClosed()) return@execute
|
||||
val newDataFeed = createDataFeed()
|
||||
subscribeImmediately(newDataFeed)
|
||||
|
||||
if (error is ConnectionFailureException) {
|
||||
reconnectingRPCConnection.observersPool.execute {
|
||||
if (unsubscribed || reconnectingRPCConnection.isClosed()) return@execute
|
||||
reconnectingRPCConnection.reconnectOnError(error)
|
||||
// It can take a while to reconnect so we might find that we've shutdown in in the meantime
|
||||
if (unsubscribed || reconnectingRPCConnection.isClosed()) return@execute
|
||||
val newDataFeed = createDataFeed()
|
||||
subscribeImmediately(newDataFeed)
|
||||
}
|
||||
} else {
|
||||
val subscriber = checkNotNull(this.subscriber.get())
|
||||
subscriber.onError(error)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
import net.corda.core.utilities.millis
|
||||
import net.corda.node.services.rpc.RPCServerConfiguration
|
||||
import net.corda.testing.internal.testThreadFactory
|
||||
import net.corda.coretesting.internal.testThreadFactory
|
||||
import net.corda.testing.node.internal.RPCDriverDSL
|
||||
import net.corda.testing.node.internal.rpcDriver
|
||||
import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet
|
||||
|
@ -5,7 +5,7 @@ import net.corda.core.messaging.RPCOps
|
||||
import net.corda.core.utilities.minutes
|
||||
import net.corda.core.utilities.seconds
|
||||
import net.corda.node.services.rpc.RPCServerConfiguration
|
||||
import net.corda.testing.internal.performance.div
|
||||
import net.corda.coretesting.internal.performance.div
|
||||
import net.corda.testing.node.internal.RPCDriverDSL
|
||||
import net.corda.testing.node.internal.performance.startPublishingFixedRateInjector
|
||||
import net.corda.testing.node.internal.performance.startReporter
|
||||
|
@ -1,30 +0,0 @@
|
||||
package net.corda.common.configuration.parsing.internal.versioned
|
||||
|
||||
import com.typesafe.config.Config
|
||||
import net.corda.common.configuration.parsing.internal.Configuration
|
||||
import net.corda.common.configuration.parsing.internal.Valid
|
||||
import net.corda.common.configuration.parsing.internal.valid
|
||||
import net.corda.common.validation.internal.Validated.Companion.invalid
|
||||
|
||||
class VersionedSpecificationRegistry<VALUE> private constructor(private val versionFromConfig: (Config) -> Valid<Int>, private val specifications: Map<Int, Configuration.Specification<VALUE>>) : (Config) -> Valid<Configuration.Specification<VALUE>> {
|
||||
|
||||
companion object {
|
||||
|
||||
fun <V> mapping(versionParser: Configuration.Value.Parser<Int>, specifications: Map<Int, Configuration.Specification<V>>) = VersionedSpecificationRegistry({ config -> versionParser.parse(config) }, specifications)
|
||||
|
||||
fun <V> mapping(versionParser: Configuration.Value.Parser<Int>, vararg specifications: Pair<Int, Configuration.Specification<V>>) = VersionedSpecificationRegistry({ config -> versionParser.parse(config) }, specifications.toMap())
|
||||
|
||||
fun <V> mapping(versionParser: (Config) -> Valid<Int>, specifications: Map<Int, Configuration.Specification<V>>) = VersionedSpecificationRegistry(versionParser, specifications)
|
||||
|
||||
fun <V> mapping(versionParser: (Config) -> Valid<Int>, vararg specifications: Pair<Int, Configuration.Specification<V>>) = VersionedSpecificationRegistry(versionParser, specifications.toMap())
|
||||
}
|
||||
|
||||
override fun invoke(configuration: Config): Valid<Configuration.Specification<VALUE>> {
|
||||
|
||||
return versionFromConfig.invoke(configuration).mapValid { version ->
|
||||
|
||||
val value = specifications[version]
|
||||
value?.let { valid(it) } ?: invalid<Configuration.Specification<VALUE>, Configuration.Validation.Error>(Configuration.Validation.Error.UnsupportedVersion.of(version))
|
||||
}
|
||||
}
|
||||
}
|
@ -1,131 +0,0 @@
|
||||
package net.corda.common.configuration.parsing.internal.versioned
|
||||
|
||||
import com.typesafe.config.Config
|
||||
import net.corda.common.configuration.parsing.internal.*
|
||||
import net.corda.common.validation.internal.Validated
|
||||
import net.corda.common.validation.internal.Validated.Companion.invalid
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Test
|
||||
|
||||
class VersionedParsingExampleTest {
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun correct_parsing_function_is_used_for_present_version() {
|
||||
|
||||
val versionParser = Configuration.Version.Extractor.fromPath("configuration.metadata.version")
|
||||
val extractVersion: (Config) -> Valid<Int> = { config -> versionParser.parseRequired(config) }
|
||||
val parseConfiguration = VersionedSpecificationRegistry.mapping(extractVersion, 1 to RpcSettingsSpec.V1, 2 to RpcSettingsSpec.V2)
|
||||
|
||||
val principalAddressValue = Address("localhost", 8080)
|
||||
val adminAddressValue = Address("127.0.0.1", 8081)
|
||||
|
||||
val configurationV1 = configObject("configuration.metadata.version" to 1, "principalHost" to principalAddressValue.host, "principalPort" to principalAddressValue.port, "adminHost" to adminAddressValue.host, "adminPort" to adminAddressValue.port).toConfig().also { println(it.serialize()) }
|
||||
val rpcSettingsFromVersion1Conf = parseConfiguration.invoke(configurationV1).mapValid { it.parse(configurationV1) }
|
||||
|
||||
assertResult(rpcSettingsFromVersion1Conf, principalAddressValue, adminAddressValue)
|
||||
|
||||
val addressesValue = configObject("principal" to "${principalAddressValue.host}:${principalAddressValue.port}", "admin" to "${adminAddressValue.host}:${adminAddressValue.port}")
|
||||
val configurationV2 = configObject("configuration.metadata.version" to 2, "configuration.value.addresses" to addressesValue).toConfig().also { println(it.serialize()) }
|
||||
val rpcSettingsFromVersion2Conf = parseConfiguration.invoke(configurationV2).mapValid { it.parse(configurationV2) }
|
||||
|
||||
assertResult(rpcSettingsFromVersion2Conf, principalAddressValue, adminAddressValue)
|
||||
}
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun default_value_is_used_for_absent_version() {
|
||||
|
||||
val defaultVersion = 2
|
||||
val versionParser = Configuration.Version.Extractor.fromPath("configuration.metadata.version", defaultVersion)
|
||||
val extractVersion: (Config) -> Valid<Int> = { config -> versionParser.parseRequired(config) }
|
||||
val parseConfiguration = VersionedSpecificationRegistry.mapping(extractVersion, 1 to RpcSettingsSpec.V1, 2 to RpcSettingsSpec.V2)
|
||||
|
||||
val principalAddressValue = Address("localhost", 8080)
|
||||
val adminAddressValue = Address("127.0.0.1", 8081)
|
||||
|
||||
val addressesValue = configObject("principal" to "${principalAddressValue.host}:${principalAddressValue.port}", "admin" to "${adminAddressValue.host}:${adminAddressValue.port}")
|
||||
val configurationV2 = configObject("configuration.value.addresses" to addressesValue).toConfig().also { println(it.serialize()) }
|
||||
val rpcSettingsFromVersion2Conf = parseConfiguration.invoke(configurationV2).mapValid { it.parse(configurationV2) }
|
||||
|
||||
assertResult(rpcSettingsFromVersion2Conf, principalAddressValue, adminAddressValue)
|
||||
}
|
||||
|
||||
private fun assertResult(result: Valid<RpcSettings>, principalAddressValue: Address, adminAddressValue: Address) {
|
||||
|
||||
assertThat(result.isValid).isTrue()
|
||||
assertThat(result.value()).satisfies { value ->
|
||||
|
||||
assertThat(value.principal).isEqualTo(principalAddressValue)
|
||||
assertThat(value.admin).isEqualTo(adminAddressValue)
|
||||
}
|
||||
}
|
||||
|
||||
private data class RpcSettings(val principal: Address, val admin: Address)
|
||||
|
||||
private object RpcSettingsSpec {
|
||||
|
||||
private fun addressFor(host: String, port: Int): Valid<Address> {
|
||||
|
||||
return try {
|
||||
require(host.isNotBlank())
|
||||
require(port > 0)
|
||||
Validated.valid(Address(host, port))
|
||||
} catch (e: Exception) {
|
||||
return Validated.invalid(Configuration.Validation.Error.BadValue.of(host, Address::class.java.simpleName, "Value must be of format \"host(String):port(Int > 0)\" e.g., \"127.0.0.1:8080\""))
|
||||
}
|
||||
}
|
||||
|
||||
object V1 : Configuration.Specification<RpcSettings>("RpcSettings") {
|
||||
|
||||
private val principalHost by string()
|
||||
private val principalPort by int()
|
||||
|
||||
private val adminHost by string()
|
||||
private val adminPort by int()
|
||||
|
||||
override fun parseValid(configuration: Config): Valid<RpcSettings> {
|
||||
|
||||
val principalHost = configuration[principalHost]
|
||||
val principalPort = configuration[principalPort]
|
||||
|
||||
val adminHost = configuration[adminHost]
|
||||
val adminPort = configuration[adminPort]
|
||||
|
||||
val principalAddress = addressFor(principalHost, principalPort)
|
||||
val adminAddress = addressFor(adminHost, adminPort)
|
||||
|
||||
return if (principalAddress.isValid && adminAddress.isValid) {
|
||||
return valid(RpcSettings(principalAddress.value(), adminAddress.value()))
|
||||
} else {
|
||||
invalid(principalAddress.errors + adminAddress.errors)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object V2 : Configuration.Specification<RpcSettings>("RpcSettings", prefix = "configuration.value") {
|
||||
|
||||
private object AddressesSpec : Configuration.Specification<Addresses>("Addresses") {
|
||||
|
||||
val principal by string().mapValid(::parseAddress)
|
||||
|
||||
val admin by string().mapValid(::parseAddress)
|
||||
|
||||
override fun parseValid(configuration: Config) = valid(Addresses(configuration[principal],configuration[admin]))
|
||||
|
||||
private fun parseAddress(rawValue: String): Valid<Address> {
|
||||
|
||||
return Address.validFromRawValue(rawValue) { error -> Configuration.Validation.Error.BadValue.of(error) }
|
||||
}
|
||||
}
|
||||
|
||||
private val addresses by nested(AddressesSpec)
|
||||
|
||||
override fun parseValid(configuration: Config): Valid<RpcSettings> {
|
||||
|
||||
val addresses = configuration[addresses]
|
||||
return valid(RpcSettings(addresses.principal, addresses.admin))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Configuration.Version.Extractor.parseRequired(config: Config, options: Configuration.Validation.Options = Configuration.Validation.Options.defaults) = parse(config, options).map { it }
|
@ -9,4 +9,4 @@ package net.corda.common.logging
|
||||
* (originally added to source control for ease of use)
|
||||
*/
|
||||
|
||||
internal const val CURRENT_MAJOR_RELEASE = "4.4-SNAPSHOT"
|
||||
internal const val CURRENT_MAJOR_RELEASE = "4.5-SNAPSHOT"
|
@ -4,11 +4,37 @@ import org.apache.logging.log4j.Level
|
||||
import org.apache.logging.log4j.message.Message
|
||||
import org.apache.logging.log4j.message.SimpleMessage
|
||||
import java.util.*
|
||||
//Returns an iterator that traverses all the exception's cause chain stopping in case of loops (an exception caused by itself)
|
||||
fun Throwable.walkExceptionCausedByList() : Iterator<Throwable> {
|
||||
val self = this
|
||||
return object : Iterator<Throwable> {
|
||||
private var cursor : Throwable? = self
|
||||
private val knownThrowables = mutableSetOf<Throwable>()
|
||||
|
||||
override fun hasNext(): Boolean {
|
||||
return cursor != null
|
||||
}
|
||||
|
||||
override fun next(): Throwable {
|
||||
val result = cursor
|
||||
val cause = cursor?.cause
|
||||
cursor = if(cause != null && knownThrowables.add(cause)) {
|
||||
cause
|
||||
} else {
|
||||
null
|
||||
}
|
||||
return result!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Message.withErrorCodeFor(error: Throwable?, level: Level): Message {
|
||||
|
||||
return when {
|
||||
error != null && level.isInRange(Level.FATAL, Level.WARN) -> CompositeMessage("$formattedMessage [errorCode=${error.errorCode()}, moreInformationAt=${error.errorCodeLocationUrl()}]", format, parameters, throwable)
|
||||
error != null && level.isInRange(Level.FATAL, Level.WARN) -> {
|
||||
val message = error.walkExceptionCausedByList().asSequence().mapNotNull(Throwable::message).joinToString(" - ")
|
||||
CompositeMessage("$message [errorCode=${error.errorCode()}, moreInformationAt=${error.errorCodeLocationUrl()}]", format, parameters, throwable)
|
||||
}
|
||||
else -> this
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,59 @@
|
||||
package net.corda.commmon.logging
|
||||
|
||||
import net.corda.common.logging.walkExceptionCausedByList
|
||||
import org.junit.Assert
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.Parameterized
|
||||
|
||||
@RunWith(Parameterized::class)
|
||||
class WalkExceptionCausedByListTest(@Suppress("UNUSED_PARAMETER") testTitle: String, private val e: Throwable, private val expectedExceptionSequence: List<Throwable>) {
|
||||
|
||||
private class TestThrowable(val id : Int, cause : Throwable?) : Throwable(cause) {
|
||||
override fun toString(): String {
|
||||
return "${this.javaClass.simpleName}(${this.id})"
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@Parameterized.Parameters(name = "{0}")
|
||||
fun data(): Collection<Array<Any>> {
|
||||
val field = Throwable::class.java.getDeclaredField("cause")
|
||||
field.isAccessible = true
|
||||
return listOf(
|
||||
run {
|
||||
val e = TestThrowable(0, null)
|
||||
arrayOf("Simple exception with no cause", e, listOf(e))
|
||||
},
|
||||
run {
|
||||
var e: TestThrowable? = null
|
||||
val exceptions = (0 until 10).map {
|
||||
e = TestThrowable(it, e)
|
||||
e
|
||||
}
|
||||
arrayOf("Exception with cause list", e!!, exceptions.asReversed())
|
||||
},
|
||||
run {
|
||||
val e = TestThrowable(0, null)
|
||||
field.set(e, e)
|
||||
arrayOf("Exception caused by itself", e, listOf(e))
|
||||
},
|
||||
run {
|
||||
val stack = mutableListOf<TestThrowable>()
|
||||
var e: TestThrowable? = null
|
||||
for(i in 0 until 10) {
|
||||
e = TestThrowable(i, stack.lastOrNull())
|
||||
stack.add(e!!)
|
||||
}
|
||||
field.set(stack[0], stack[4])
|
||||
arrayOf("Exception with loop in cause list", e!!, stack.asReversed())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@Test(timeout = 1000)
|
||||
fun test() {
|
||||
Assert.assertEquals(expectedExceptionSequence, e.walkExceptionCausedByList().asSequence().toList())
|
||||
}
|
||||
}
|
@ -13,7 +13,6 @@ import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.core.internal.VisibleForTesting
|
||||
import net.corda.core.internal.cordapp.CordappResolver
|
||||
import net.corda.core.internal.warnOnce
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
@ -95,7 +94,7 @@ private constructor(private val otherSideSession: FlowSession?,
|
||||
override fun call(): LinkedHashMap<Party, AnonymousParty> {
|
||||
val session = if (otherParty != null && otherParty != otherSideSession?.counterparty) {
|
||||
logger.warnOnce("The current usage of SwapIdentitiesFlow is unsafe. Please consider upgrading your CorDapp to use " +
|
||||
"SwapIdentitiesFlow with FlowSessions. (${CordappResolver.currentCordapp?.info})")
|
||||
"SwapIdentitiesFlow with FlowSessions. (${serviceHub.getAppContext().cordapp.info})")
|
||||
initiateFlow(otherParty)
|
||||
} else {
|
||||
otherSideSession!!
|
||||
|
@ -15,9 +15,9 @@ import net.corda.core.identity.AnonymousParty
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.PartyAndCertificate
|
||||
import net.corda.testing.core.*
|
||||
import net.corda.testing.internal.matchers.allOf
|
||||
import net.corda.testing.internal.matchers.flow.willReturn
|
||||
import net.corda.testing.internal.matchers.hasOnlyEntries
|
||||
import net.corda.coretesting.internal.matchers.allOf
|
||||
import net.corda.coretesting.internal.matchers.flow.willReturn
|
||||
import net.corda.coretesting.internal.matchers.hasOnlyEntries
|
||||
import net.corda.testing.node.internal.InternalMockNetwork
|
||||
import net.corda.testing.node.internal.TestStartedNode
|
||||
import net.corda.testing.node.internal.enclosedCordapp
|
||||
|
@ -66,8 +66,8 @@
|
||||
<PatternLayout pattern="%msg%n%throwable{0}" />
|
||||
</Console>
|
||||
|
||||
<!-- Will generate up to 100 log files for a given day. During every rollover it will delete
|
||||
those that are older than 60 days, but keep the most recent 10 GB -->
|
||||
<!-- Will generate up to 500 log files for a given day. Adjust this number according to the available storage.
|
||||
During every rollover it will delete those that are older than 60 days, but keep the most recent 10 GB -->
|
||||
<RollingRandomAccessFile name="RollingFile-Appender"
|
||||
fileName="${log-path}/${log-name}.log"
|
||||
filePattern="${archive}/${log-name}.%date{yyyy-MM-dd}-%i.log.gz">
|
||||
@ -93,7 +93,7 @@
|
||||
<SizeBasedTriggeringPolicy size="100MB"/>
|
||||
</Policies>
|
||||
|
||||
<DefaultRolloverStrategy min="1" max="100">
|
||||
<DefaultRolloverStrategy min="1" max="500">
|
||||
<Delete basePath="${archive}" maxDepth="1">
|
||||
<IfFileName glob="${log-name}*.log.gz"/>
|
||||
<IfLastModified age="60d">
|
||||
|
@ -2,9 +2,9 @@
|
||||
# because some versions here need to be matched by app authors in
|
||||
# their own projects. So don't get fancy with syntax!
|
||||
|
||||
cordaVersion=4.4
|
||||
cordaVersion=4.5
|
||||
versionSuffix=SNAPSHOT
|
||||
gradlePluginsVersion=5.0.6
|
||||
gradlePluginsVersion=5.0.8
|
||||
kotlinVersion=1.2.71
|
||||
java8MinUpdateVersion=171
|
||||
# ***************************************************************#
|
||||
@ -30,9 +30,10 @@ snakeYamlVersion=1.19
|
||||
caffeineVersion=2.7.0
|
||||
metricsVersion=4.1.0
|
||||
metricsNewRelicVersion=1.1.1
|
||||
djvmVersion=1.0-RC09
|
||||
djvmVersion=1.0-RC10
|
||||
deterministicRtVersion=1.0-RC02
|
||||
openSourceBranch=https://github.com/corda/corda/blob/release/os/4.4
|
||||
openSourceSamplesBranch=https://github.com/corda/samples/blob/release-V4
|
||||
jolokiaAgentVersion=1.6.1
|
||||
detektVersion=1.0.1
|
||||
|
||||
|
@ -1,10 +1,18 @@
|
||||
description 'Corda core (deterministic)'
|
||||
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
|
||||
|
||||
apply from: '../deterministic.gradle'
|
||||
apply plugin: 'com.jfrog.artifactory'
|
||||
apply plugin: 'net.corda.plugins.publish-utils'
|
||||
apply plugin: 'java-library'
|
||||
apply plugin: 'idea'
|
||||
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")
|
||||
|
||||
@ -39,7 +47,7 @@ dependencies {
|
||||
deterministicLibraries "net.i2p.crypto:eddsa:$eddsa_version"
|
||||
}
|
||||
|
||||
jar {
|
||||
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.
|
||||
@ -49,7 +57,8 @@ jar {
|
||||
def coreJarTask = tasks.getByPath(':core:jar')
|
||||
def originalJar = coreJarTask.outputs.files.singleFile
|
||||
|
||||
task patchCore(type: Zip, dependsOn: coreJarTask) {
|
||||
def patchCore = tasks.register('patchCore', Zip) {
|
||||
dependsOn coreJarTask
|
||||
destinationDirectory = file("$buildDir/source-libs")
|
||||
metadataCharset 'UTF-8'
|
||||
archiveClassifier = 'transient'
|
||||
@ -70,8 +79,7 @@ task patchCore(type: Zip, dependsOn: coreJarTask) {
|
||||
includeEmptyDirs = false
|
||||
}
|
||||
|
||||
import proguard.gradle.ProGuardTask
|
||||
task predeterminise(type: ProGuardTask) {
|
||||
def predeterminise = tasks.register('predeterminise', ProGuardTask) {
|
||||
injars patchCore
|
||||
outjars file("$buildDir/proguard/pre-deterministic-${project.version}.jar")
|
||||
|
||||
@ -104,8 +112,7 @@ task predeterminise(type: ProGuardTask) {
|
||||
keepclassmembers 'class net.corda.core.** { public synthetic <methods>; }'
|
||||
}
|
||||
|
||||
import net.corda.gradle.jarfilter.JarFilterTask
|
||||
task jarFilter(type: JarFilterTask) {
|
||||
def jarFilter = tasks.register('jarFilter', JarFilterTask) {
|
||||
jars predeterminise
|
||||
annotations {
|
||||
forDelete = [
|
||||
@ -158,9 +165,6 @@ task determinise(type: ProGuardTask) {
|
||||
keepclassmembers 'class net.corda.core.** { public synthetic <methods>; }'
|
||||
}
|
||||
|
||||
import net.corda.gradle.jarfilter.MetaFixerTask
|
||||
import static org.gradle.api.JavaVersion.VERSION_1_8
|
||||
|
||||
task metafix(type: MetaFixerTask) {
|
||||
outputDir file("$buildDir/libs")
|
||||
jars determinise
|
||||
@ -171,7 +175,8 @@ task metafix(type: MetaFixerTask) {
|
||||
}
|
||||
|
||||
// DOCSTART 01
|
||||
task checkDeterminism(type: ProGuardTask, dependsOn: jdkTask) {
|
||||
def checkDeterminism = tasks.register('checkDeterminism', ProGuardTask) {
|
||||
dependsOn jdkTask
|
||||
injars metafix
|
||||
|
||||
libraryjars deterministic_rt_jar
|
||||
|
@ -1,25 +1,29 @@
|
||||
apply plugin: 'kotlin'
|
||||
plugins {
|
||||
id 'org.jetbrains.kotlin.jvm'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile project(path: ':core-deterministic', configuration: 'deterministicArtifacts')
|
||||
testCompile project(path: ':serialization-deterministic', configuration: 'deterministicArtifacts')
|
||||
testCompile project(path: ':core-deterministic:testing:verifier', configuration: 'deterministicArtifacts')
|
||||
testCompile project(path: ':core-deterministic:testing:data', configuration: 'testData')
|
||||
testCompile(project(':finance:contracts')) {
|
||||
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
|
||||
}
|
||||
testCompile(project(':finance:workflows')) {
|
||||
testImplementation(project(':finance:workflows')) {
|
||||
transitive = false
|
||||
}
|
||||
|
||||
testImplementation "org.slf4j:slf4j-api:$slf4j_version"
|
||||
testRuntimeOnly "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version"
|
||||
testCompile "org.jetbrains.kotlin:kotlin-test:$kotlin_version"
|
||||
testCompile "org.assertj:assertj-core:$assertj_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.
|
||||
jar.enabled = false
|
||||
tasks.named('jar', Jar) {
|
||||
enabled = false
|
||||
}
|
||||
|
@ -1,17 +1,19 @@
|
||||
apply plugin: 'kotlin'
|
||||
plugins {
|
||||
id 'org.jetbrains.kotlin.jvm'
|
||||
}
|
||||
|
||||
configurations {
|
||||
testData
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testCompile project(':core')
|
||||
testCompile project(':finance:workflows')
|
||||
testCompile project(':node-driver')
|
||||
testCompile project(path: ':core-deterministic:testing:verifier', configuration: 'runtimeArtifacts')
|
||||
testImplementation project(':core')
|
||||
testImplementation project(':finance:workflows')
|
||||
testImplementation project(':node-driver')
|
||||
testImplementation project(path: ':core-deterministic:testing:verifier', configuration: 'runtimeArtifacts')
|
||||
|
||||
testCompile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
|
||||
testCompile "org.jetbrains.kotlin:kotlin-reflect"
|
||||
testImplementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
|
||||
testImplementation "org.jetbrains.kotlin:kotlin-reflect"
|
||||
|
||||
testImplementation "junit:junit:$junit_version"
|
||||
|
||||
@ -19,7 +21,9 @@ dependencies {
|
||||
testRuntimeOnly "org.junit.platform:junit-platform-launcher:${junit_platform_version}"
|
||||
}
|
||||
|
||||
jar.enabled = false
|
||||
tasks.named('jar', Jar) {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
test {
|
||||
ext {
|
||||
|
@ -71,7 +71,7 @@ class GenerateData {
|
||||
testSerialization.reset()
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(timeout = 300_000)
|
||||
fun verifyTransactions() {
|
||||
URLClassLoader(arrayOf(TEST_DATA.toUri().toURL())).use { cl ->
|
||||
cl.loadResource("txverify/tx-success.bin")
|
||||
|
@ -1,8 +1,10 @@
|
||||
apply plugin: 'java-library'
|
||||
apply from: '../../../deterministic.gradle'
|
||||
apply plugin: 'net.corda.plugins.publish-utils'
|
||||
apply plugin: 'com.jfrog.artifactory'
|
||||
apply plugin: 'idea'
|
||||
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'
|
||||
|
||||
|
@ -47,7 +47,7 @@ class RequireSingleCommandTests(private val testFunction: (Collection<CommandWit
|
||||
assertEquals(returnedCommand, validCommandOne, "they should be the same")
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException::class)
|
||||
@Test(expected = IllegalArgumentException::class, timeout=300_000)
|
||||
fun `check error is thrown if more than one valid command`() {
|
||||
val commands = listOf(validCommandOne, validCommandTwo)
|
||||
testFunction(commands)
|
||||
|
@ -181,7 +181,7 @@ class CompositeKeyTests {
|
||||
assertFalse { engine.verify(CompositeSignaturesWithKeys(listOf(aliceSignature, brokenBobSignature)).serialize().bytes) }
|
||||
}
|
||||
|
||||
@Test()
|
||||
@Test(timeout=300_000)
|
||||
fun `composite key constraints`() {
|
||||
// Zero weight.
|
||||
assertFailsWith(IllegalArgumentException::class) {
|
||||
@ -223,7 +223,7 @@ class CompositeKeyTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test()
|
||||
@Test(timeout=300_000)
|
||||
fun `composite key validation with graph cycle detection`() = kryoSpecific("Cycle exists in the object graph which is not currently supported in AMQP mode") {
|
||||
val key1 = CompositeKey.Builder().addKeys(alicePublicKey, bobPublicKey).build() as CompositeKey
|
||||
val key2 = CompositeKey.Builder().addKeys(alicePublicKey, key1).build() as CompositeKey
|
||||
|
@ -24,7 +24,7 @@ import net.corda.testing.core.TestIdentity
|
||||
import net.corda.testing.dsl.LedgerDSL
|
||||
import net.corda.testing.dsl.TestLedgerDSLInterpreter
|
||||
import net.corda.testing.dsl.TestTransactionDSLInterpreter
|
||||
import net.corda.testing.internal.TEST_TX_TIME
|
||||
import net.corda.coretesting.internal.TEST_TX_TIME
|
||||
import net.corda.testing.internal.createWireTransaction
|
||||
import net.corda.testing.node.MockServices
|
||||
import net.corda.testing.node.ledger
|
||||
@ -270,7 +270,7 @@ class PartialMerkleTreeTest {
|
||||
assertFalse(pmt.verify(wrongRoot, inclHashes))
|
||||
}
|
||||
|
||||
@Test(expected = Exception::class)
|
||||
@Test(expected = Exception::class, timeout=300_000)
|
||||
fun `hash map serialization not allowed`() {
|
||||
val hm1 = hashMapOf("a" to 1, "b" to 2, "c" to 3, "e" to 4)
|
||||
hm1.serialize()
|
||||
|
@ -35,7 +35,7 @@ class SignedDataTest {
|
||||
assertEquals(data, unwrappedData)
|
||||
}
|
||||
|
||||
@Test(expected = SignatureException::class)
|
||||
@Test(expected = SignatureException::class, timeout=300_000)
|
||||
fun `make sure incorrectly signed data raises an exception`() {
|
||||
val keyPairA = generateKeyPair()
|
||||
val keyPairB = generateKeyPair()
|
||||
|
@ -39,7 +39,7 @@ class TransactionSignatureTest {
|
||||
}
|
||||
|
||||
/** Verification should fail; corrupted metadata - clearData (Merkle root) has changed. */
|
||||
@Test(expected = SignatureException::class)
|
||||
@Test(expected = SignatureException::class,timeout=300_000)
|
||||
fun `Signature metadata full failure clearData has changed`() {
|
||||
val keyPair = Crypto.generateKeyPair("ECDSA_SECP256K1_SHA256")
|
||||
val signableData = SignableData(testBytes.sha256(), SignatureMetadata(1, Crypto.findSignatureScheme(keyPair.public).schemeNumberID))
|
||||
|
@ -21,8 +21,8 @@ import net.corda.testing.core.BOB_NAME
|
||||
import net.corda.testing.core.makeUnique
|
||||
import net.corda.testing.core.singleIdentity
|
||||
import net.corda.testing.internal.fakeAttachment
|
||||
import net.corda.testing.internal.matchers.flow.willReturn
|
||||
import net.corda.testing.internal.matchers.flow.willThrow
|
||||
import net.corda.coretesting.internal.matchers.flow.willReturn
|
||||
import net.corda.coretesting.internal.matchers.flow.willThrow
|
||||
import net.corda.testing.node.internal.InternalMockNetwork
|
||||
import net.corda.testing.node.internal.InternalMockNodeParameters
|
||||
import net.corda.testing.node.internal.TestStartedNode
|
||||
|
@ -30,9 +30,9 @@ 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.internal.matchers.flow.willReturn
|
||||
import net.corda.testing.internal.matchers.flow.willThrow
|
||||
import net.corda.testing.internal.rigorousMock
|
||||
import net.corda.coretesting.internal.matchers.flow.willReturn
|
||||
import net.corda.coretesting.internal.matchers.flow.willThrow
|
||||
import net.corda.coretesting.internal.rigorousMock
|
||||
import net.corda.testing.node.MockServices
|
||||
import net.corda.testing.node.internal.DUMMY_CONTRACTS_CORDAPP
|
||||
import net.corda.testing.node.internal.InternalMockNetwork
|
||||
@ -127,7 +127,7 @@ class CollectSignaturesFlowTests : WithContracts {
|
||||
Assert.assertThat(missingSigners, `is`(emptySet()))
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException::class)
|
||||
@Test(expected = IllegalArgumentException::class, timeout=300_000)
|
||||
fun `throws exception when extra sessions are initiated`() {
|
||||
bobNode.registerInitiatedFlow(ExtraSessionsFlowResponder::class.java)
|
||||
charlieNode.registerInitiatedFlow(ExtraSessionsFlowResponder::class.java)
|
||||
|
@ -18,8 +18,8 @@ import net.corda.testing.contracts.DummyContractV2
|
||||
import net.corda.testing.core.ALICE_NAME
|
||||
import net.corda.testing.core.BOB_NAME
|
||||
import net.corda.testing.core.singleIdentity
|
||||
import net.corda.testing.internal.matchers.rpc.willReturn
|
||||
import net.corda.testing.internal.matchers.rpc.willThrow
|
||||
import net.corda.coretesting.internal.matchers.rpc.willReturn
|
||||
import net.corda.coretesting.internal.matchers.rpc.willThrow
|
||||
import net.corda.testing.node.User
|
||||
import net.corda.testing.node.internal.*
|
||||
import org.junit.AfterClass
|
||||
|
@ -20,8 +20,8 @@ import net.corda.testing.contracts.DummyContractV3
|
||||
import net.corda.testing.core.ALICE_NAME
|
||||
import net.corda.testing.core.BOB_NAME
|
||||
import net.corda.testing.core.singleIdentity
|
||||
import net.corda.testing.internal.matchers.flow.willReturn
|
||||
import net.corda.testing.internal.matchers.flow.willThrow
|
||||
import net.corda.coretesting.internal.matchers.flow.willReturn
|
||||
import net.corda.coretesting.internal.matchers.flow.willThrow
|
||||
import net.corda.testing.node.internal.*
|
||||
import org.junit.AfterClass
|
||||
import org.junit.Test
|
||||
|
@ -4,7 +4,6 @@ import com.natpryce.hamkrest.and
|
||||
import com.natpryce.hamkrest.assertion.assertThat
|
||||
import net.corda.core.flows.FinalityFlow
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.cordapp.CordappResolver
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.getOrThrow
|
||||
@ -13,8 +12,8 @@ import net.corda.finance.POUNDS
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.finance.issuedBy
|
||||
import net.corda.testing.core.*
|
||||
import net.corda.testing.internal.matchers.flow.willReturn
|
||||
import net.corda.testing.internal.matchers.flow.willThrow
|
||||
import net.corda.coretesting.internal.matchers.flow.willReturn
|
||||
import net.corda.coretesting.internal.matchers.flow.willThrow
|
||||
import net.corda.testing.node.internal.*
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.After
|
||||
@ -25,7 +24,8 @@ class FinalityFlowTests : WithFinality {
|
||||
private val CHARLIE = TestIdentity(CHARLIE_NAME, 90).party
|
||||
}
|
||||
|
||||
override val mockNet = InternalMockNetwork(cordappsForAllNodes = listOf(FINANCE_CONTRACTS_CORDAPP, enclosedCordapp()))
|
||||
override val mockNet = InternalMockNetwork(cordappsForAllNodes = listOf(FINANCE_CONTRACTS_CORDAPP, enclosedCordapp(),
|
||||
CustomCordapp(targetPlatformVersion = 3, classes = setOf(FinalityFlow::class.java))))
|
||||
|
||||
private val aliceNode = makeNode(ALICE_NAME)
|
||||
|
||||
@ -60,11 +60,8 @@ class FinalityFlowTests : WithFinality {
|
||||
fun `allow use of the old API if the CorDapp target version is 3`() {
|
||||
val oldBob = createBob(cordapps = listOf(tokenOldCordapp()))
|
||||
val stx = aliceNode.issuesCashTo(oldBob)
|
||||
val resultFuture = CordappResolver.withTestCordapp(targetPlatformVersion = 3) {
|
||||
@Suppress("DEPRECATION")
|
||||
aliceNode.startFlowAndRunNetwork(FinalityFlow(stx)).resultFuture
|
||||
}
|
||||
resultFuture.getOrThrow()
|
||||
@Suppress("DEPRECATION")
|
||||
aliceNode.startFlowAndRunNetwork(FinalityFlow(stx)).resultFuture.getOrThrow()
|
||||
assertThat(oldBob.services.validatedTransactions.getTransaction(stx.id)).isNotNull()
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ import net.corda.testing.core.singleIdentity
|
||||
import net.corda.testing.flows.from
|
||||
import net.corda.testing.flows.receiveAll
|
||||
import net.corda.testing.flows.registerCordappFlowFactory
|
||||
import net.corda.testing.internal.matchers.flow.willReturn
|
||||
import net.corda.coretesting.internal.matchers.flow.willReturn
|
||||
import net.corda.testing.node.internal.InternalMockNetwork
|
||||
import net.corda.testing.node.internal.TestStartedNode
|
||||
import org.junit.AfterClass
|
||||
|
@ -12,7 +12,7 @@ import net.corda.nodeapi.internal.crypto.X509KeyStore
|
||||
import net.corda.nodeapi.internal.crypto.X509Utilities
|
||||
import net.corda.testing.core.SerializationEnvironmentRule
|
||||
import net.corda.testing.core.getTestPartyAndCertificate
|
||||
import net.corda.testing.internal.DEV_ROOT_CA
|
||||
import net.corda.coretesting.internal.DEV_ROOT_CA
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
@ -19,8 +19,8 @@ import net.corda.testing.common.internal.testNetworkParameters
|
||||
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
||||
import net.corda.testing.core.SerializationEnvironmentRule
|
||||
import net.corda.testing.core.TestIdentity
|
||||
import net.corda.testing.internal.TEST_TX_TIME
|
||||
import net.corda.testing.internal.rigorousMock
|
||||
import net.corda.coretesting.internal.TEST_TX_TIME
|
||||
import net.corda.coretesting.internal.rigorousMock
|
||||
import net.corda.testing.node.MockServices
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
|
@ -20,7 +20,7 @@ import net.corda.testing.common.internal.testNetworkParameters
|
||||
import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.contracts.DummyState
|
||||
import net.corda.testing.core.*
|
||||
import net.corda.testing.internal.rigorousMock
|
||||
import net.corda.coretesting.internal.rigorousMock
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.junit.Assert.assertFalse
|
||||
|
@ -17,7 +17,7 @@ import net.corda.testing.contracts.DummyContract
|
||||
import net.corda.testing.core.*
|
||||
import net.corda.testing.internal.createWireTransaction
|
||||
import net.corda.testing.internal.fakeAttachment
|
||||
import net.corda.testing.internal.rigorousMock
|
||||
import net.corda.coretesting.internal.rigorousMock
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import java.math.BigInteger
|
||||
|
@ -7,7 +7,7 @@ import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.internal.checkpointDeserialize
|
||||
import net.corda.core.serialization.internal.checkpointSerialize
|
||||
import net.corda.core.utilities.transient
|
||||
import net.corda.node.serialization.kryo.KRYO_CHECKPOINT_CONTEXT
|
||||
import net.corda.nodeapi.internal.serialization.kryo.KRYO_CHECKPOINT_CONTEXT
|
||||
import net.corda.serialization.internal.CheckpointSerializationContextImpl
|
||||
import net.corda.testing.core.SerializationEnvironmentRule
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
|
@ -82,7 +82,7 @@ dependencies {
|
||||
testCompile "org.ow2.asm:asm:$asm_version"
|
||||
|
||||
// JDK11: required by Quasar at run-time
|
||||
testRuntimeOnly "com.esotericsoftware:kryo:4.0.2"
|
||||
testRuntimeOnly "com.esotericsoftware:kryo:$kryo_version"
|
||||
|
||||
testCompile "com.nhaarman:mockito-kotlin:$mockito_kotlin_version"
|
||||
testCompile "org.mockito:mockito-core:$mockito_version"
|
||||
|
@ -134,8 +134,7 @@ interface LinearState : ContractState {
|
||||
val linearId: UniqueIdentifier
|
||||
}
|
||||
// DOCEND 2
|
||||
|
||||
@KeepForDJVM
|
||||
@DeleteForDJVM
|
||||
interface SchedulableState : ContractState {
|
||||
/**
|
||||
* Indicate whether there is some activity to be performed at some future point in time with respect to this
|
||||
@ -146,7 +145,6 @@ interface SchedulableState : ContractState {
|
||||
*
|
||||
* @return null if there is no activity to schedule.
|
||||
*/
|
||||
@DeleteForDJVM
|
||||
fun nextScheduledActivity(thisStateRef: StateRef, flowLogicRefFactory: FlowLogicRefFactory): ScheduledActivity?
|
||||
}
|
||||
|
||||
@ -176,6 +174,7 @@ data class StateAndRef<out T : ContractState>(val state: TransactionState<T>, va
|
||||
// DOCEND 7
|
||||
|
||||
/** 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>)
|
||||
|
||||
/** Filters a list of [StateAndRef] objects according to the type of the states */
|
||||
|
@ -5,7 +5,6 @@ import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.isFulfilledBy
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.identity.groupAbstractPartyByWellKnownParty
|
||||
import net.corda.core.internal.cordapp.CordappResolver
|
||||
import net.corda.core.internal.pushToLoggingContext
|
||||
import net.corda.core.internal.warnOnce
|
||||
import net.corda.core.node.StatesToRecord
|
||||
@ -136,7 +135,7 @@ class FinalityFlow private constructor(val transaction: SignedTransaction,
|
||||
override fun call(): SignedTransaction {
|
||||
if (!newApi) {
|
||||
logger.warnOnce("The current usage of FinalityFlow is unsafe. Please consider upgrading your CorDapp to use " +
|
||||
"FinalityFlow with FlowSessions. (${CordappResolver.currentCordapp?.info})")
|
||||
"FinalityFlow with FlowSessions. (${serviceHub.getAppContext().cordapp.info})")
|
||||
} else {
|
||||
require(sessions.none { serviceHub.myInfo.isLegalIdentity(it.counterparty) }) {
|
||||
"Do not provide flow sessions for the local node. FinalityFlow will record the notarised transaction locally."
|
||||
|
@ -25,6 +25,7 @@ import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.SerializationDefaults
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
@ -317,6 +318,53 @@ abstract class FlowLogic<out T> {
|
||||
return castMapValuesToKnownType(receiveAllMap(associateSessionsToReceiveType(receiveType, sessions)))
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues the given [payload] for sending to the provided [sessions] and continues without suspending.
|
||||
*
|
||||
* Note that the other parties may receive the message at some arbitrary later point or not at all: if one of the provided [sessions]
|
||||
* is offline then message delivery will be retried until the corresponding node comes back or until the message is older than the
|
||||
* network's event horizon time.
|
||||
*
|
||||
* @param payload the payload to send.
|
||||
* @param sessions the sessions to send the provided payload to.
|
||||
* @param maySkipCheckpoint whether checkpointing should be skipped.
|
||||
*/
|
||||
@Suspendable
|
||||
@JvmOverloads
|
||||
fun sendAll(payload: Any, sessions: Set<FlowSession>, maySkipCheckpoint: Boolean = false) {
|
||||
val sessionToPayload = sessions.map { it to payload }.toMap()
|
||||
return sendAll(sessionToPayload, maySkipCheckpoint)
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues the given payloads for sending to the provided sessions and continues without suspending.
|
||||
*
|
||||
* Note that the other parties may receive the message at some arbitrary later point or not at all: if one of the provided [sessions]
|
||||
* is offline then message delivery will be retried until the corresponding node comes back or until the message is older than the
|
||||
* network's event horizon time.
|
||||
*
|
||||
* @param payloadsPerSession a mapping that contains the payload to be sent to each session.
|
||||
* @param maySkipCheckpoint whether checkpointing should be skipped.
|
||||
*/
|
||||
@Suspendable
|
||||
@JvmOverloads
|
||||
fun sendAll(payloadsPerSession: Map<FlowSession, Any>, maySkipCheckpoint: Boolean = false) {
|
||||
val request = FlowIORequest.Send(
|
||||
sessionToMessage = serializePayloads(payloadsPerSession)
|
||||
)
|
||||
stateMachine.suspend(request, maySkipCheckpoint)
|
||||
}
|
||||
|
||||
@Suspendable
|
||||
private fun serializePayloads(payloadsPerSession: Map<FlowSession, Any>): Map<FlowSession, SerializedBytes<Any>> {
|
||||
val cachedSerializedPayloads = mutableMapOf<Any, SerializedBytes<Any>>()
|
||||
|
||||
return payloadsPerSession.mapValues { (_, payload) ->
|
||||
cachedSerializedPayloads[payload] ?: payload.serialize(context = SerializationDefaults.P2P_CONTEXT).also { cachedSerializedPayloads[payload] = it }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Invokes the given subflow. This function returns once the subflow completes successfully with the result
|
||||
* returned by that subflow's [call] method. If the subflow has a progress tracker, it is attached to the
|
||||
|
@ -4,7 +4,12 @@ package net.corda.core.internal
|
||||
|
||||
import net.corda.core.DeleteForDJVM
|
||||
import net.corda.core.KeepForDJVM
|
||||
import net.corda.core.crypto.*
|
||||
import net.corda.core.crypto.Crypto
|
||||
import net.corda.core.crypto.DigitalSignature
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.SignedData
|
||||
import net.corda.core.crypto.sha256
|
||||
import net.corda.core.crypto.sign
|
||||
import net.corda.core.serialization.SerializationDefaults
|
||||
import net.corda.core.serialization.SerializedBytes
|
||||
import net.corda.core.serialization.deserialize
|
||||
@ -40,11 +45,23 @@ import java.security.KeyPair
|
||||
import java.security.MessageDigest
|
||||
import java.security.PrivateKey
|
||||
import java.security.PublicKey
|
||||
import java.security.cert.*
|
||||
import java.security.cert.CertPath
|
||||
import java.security.cert.CertPathValidator
|
||||
import java.security.cert.CertPathValidatorException
|
||||
import java.security.cert.PKIXCertPathValidatorResult
|
||||
import java.security.cert.PKIXParameters
|
||||
import java.security.cert.TrustAnchor
|
||||
import java.security.cert.X509Certificate
|
||||
import java.time.Duration
|
||||
import java.time.temporal.Temporal
|
||||
import java.util.*
|
||||
import java.util.Spliterator.*
|
||||
import java.util.Spliterator.DISTINCT
|
||||
import java.util.Spliterator.IMMUTABLE
|
||||
import java.util.Spliterator.NONNULL
|
||||
import java.util.Spliterator.ORDERED
|
||||
import java.util.Spliterator.SIZED
|
||||
import java.util.Spliterator.SORTED
|
||||
import java.util.Spliterator.SUBSIZED
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.stream.Collectors
|
||||
@ -78,6 +95,8 @@ infix fun Temporal.until(endExclusive: Temporal): Duration = Duration.between(th
|
||||
operator fun Duration.div(divider: Long): Duration = dividedBy(divider)
|
||||
operator fun Duration.times(multiplicand: Long): Duration = multipliedBy(multiplicand)
|
||||
operator fun Duration.times(multiplicand: Double): Duration = Duration.ofNanos((toNanos() * multiplicand).roundToLong())
|
||||
fun min(d1: Duration, d2: Duration): Duration = if (d1 <= d2) d1 else d2
|
||||
|
||||
|
||||
/**
|
||||
* Returns the single element matching the given [predicate], or `null` if the collection is empty, or throws exception
|
||||
@ -173,6 +192,9 @@ fun <T> Observable<T>.bufferUntilSubscribed(): Observable<T> {
|
||||
@DeleteForDJVM
|
||||
fun <T> Observer<T>.tee(vararg teeTo: Observer<T>): Observer<T> {
|
||||
val subject = PublishSubject.create<T>()
|
||||
// use unsafe subscribe, so that the teed subscribers will not get wrapped with SafeSubscribers,
|
||||
// therefore a potential raw exception (non Rx) coming from a child -unsafe subscribed- observer
|
||||
// will not unsubscribe all of the subscribers under the PublishSubject.
|
||||
subject.unsafeSubscribe(Subscribers.from(this))
|
||||
teeTo.forEach { subject.unsafeSubscribe(Subscribers.from(it)) }
|
||||
return subject
|
||||
|
@ -78,6 +78,7 @@ fun <ELEMENT> CordaFuture<out ELEMENT>.mapError(transform: (Throwable) -> Throwa
|
||||
* But if this future or the transform fails, the returned future's outcome is the same throwable.
|
||||
* In the case where this future fails, the transform is not invoked.
|
||||
*/
|
||||
@Suppress("TooGenericExceptionCaught")
|
||||
fun <V, W> CordaFuture<out V>.flatMap(transform: (V) -> CordaFuture<out W>): CordaFuture<W> = CordaFutureImpl<W>().also { result ->
|
||||
thenMatch(success@ {
|
||||
result.captureLater(try {
|
||||
@ -85,6 +86,9 @@ fun <V, W> CordaFuture<out V>.flatMap(transform: (V) -> CordaFuture<out W>): Cor
|
||||
} catch (e: Exception) {
|
||||
result.setException(e)
|
||||
return@success
|
||||
} catch (t: Throwable) {
|
||||
result.setException(t)
|
||||
throw t
|
||||
})
|
||||
}, {
|
||||
result.setException(it)
|
||||
@ -136,11 +140,15 @@ interface ValueOrException<in V> {
|
||||
fun captureLater(f: CordaFuture<out V>) = f.then { capture { f.getOrThrow() } }
|
||||
|
||||
/** Run the given block (in the foreground) and set this future to its outcome. */
|
||||
@Suppress("TooGenericExceptionCaught")
|
||||
fun capture(block: () -> V): Boolean {
|
||||
return set(try {
|
||||
block()
|
||||
} catch (e: Exception) {
|
||||
return setException(e)
|
||||
} catch (t: Throwable) {
|
||||
setException(t)
|
||||
throw t
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -160,12 +168,16 @@ internal class CordaFutureImpl<V>(private val impl: CompletableFuture<V> = Compl
|
||||
override fun setException(t: Throwable) = impl.completeExceptionally(t)
|
||||
override fun <W> then(callback: (CordaFuture<V>) -> W) = thenImpl(defaultLog, callback)
|
||||
/** For testing only. */
|
||||
@Suppress("TooGenericExceptionCaught")
|
||||
internal fun <W> thenImpl(log: Logger, callback: (CordaFuture<V>) -> W) {
|
||||
impl.whenComplete { _, _ ->
|
||||
try {
|
||||
callback(this)
|
||||
} catch (e: Exception) {
|
||||
log.error(listenerFailedMessage, e)
|
||||
} catch (t: Throwable) {
|
||||
log.error(listenerFailedMessage, t)
|
||||
throw t
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,133 +0,0 @@
|
||||
package net.corda.core.internal.cordapp
|
||||
|
||||
import net.corda.core.cordapp.Cordapp
|
||||
import net.corda.core.internal.PLATFORM_VERSION
|
||||
import net.corda.core.internal.VisibleForTesting
|
||||
import net.corda.core.internal.warnOnce
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
/**
|
||||
* Provides a way to acquire information about the calling CorDapp.
|
||||
*/
|
||||
object CordappResolver {
|
||||
|
||||
private val logger = loggerFor<CordappResolver>()
|
||||
private val cordappClasses: ConcurrentHashMap<String, Set<Cordapp>> = ConcurrentHashMap()
|
||||
|
||||
private val insideInMemoryTest: Boolean by lazy { insideInMemoryTest() }
|
||||
|
||||
// TODO Use the StackWalker API once we migrate to Java 9+
|
||||
private var cordappResolver: () -> Cordapp? = {
|
||||
Exception().stackTrace
|
||||
.mapNotNull { cordappClasses[it.className] }
|
||||
// in case there are multiple classes matched, we select the first one having a single CorDapp registered against it.
|
||||
.firstOrNull { it.size == 1 }
|
||||
// otherwise we return null, signalling we cannot reliably determine the current CorDapp.
|
||||
?.single()
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates class names with CorDapps or logs a warning when a CorDapp is already registered for a given class.
|
||||
* This could happen when trying to run different versions of the same CorDapp on the same node.
|
||||
*
|
||||
* @throws IllegalStateException when multiple CorDapps are registered for the same contract class,
|
||||
* since this can lead to undefined behaviour.
|
||||
*/
|
||||
@Synchronized
|
||||
fun register(cordapp: Cordapp) {
|
||||
val contractClasses = cordapp.contractClassNames.toSet()
|
||||
val existingClasses = cordappClasses.keys
|
||||
val classesToRegister = cordapp.cordappClasses.toSet()
|
||||
val notAlreadyRegisteredClasses = classesToRegister - existingClasses
|
||||
val alreadyRegistered= HashMap(cordappClasses).apply { keys.retainAll(classesToRegister) }
|
||||
|
||||
notAlreadyRegisteredClasses.forEach { cordappClasses[it] = setOf(cordapp) }
|
||||
|
||||
for ((registeredClassName, registeredCordapps) in alreadyRegistered) {
|
||||
val duplicateCordapps = registeredCordapps.filter { it.jarHash == cordapp.jarHash }.toSet()
|
||||
|
||||
if (duplicateCordapps.isNotEmpty()) {
|
||||
logger.warnOnce("The CorDapp (name: ${cordapp.info.shortName}, file: ${cordapp.name}) " +
|
||||
"is installed multiple times on the node. The following files correspond to the exact same content: " +
|
||||
"${duplicateCordapps.map { it.name }}")
|
||||
continue
|
||||
}
|
||||
// During in-memory tests, the spawned nodes share the same CordappResolver, so detected conflicts can be spurious.
|
||||
if (registeredClassName in contractClasses && !insideInMemoryTest) {
|
||||
throw IllegalStateException("More than one CorDapp installed on the node for contract $registeredClassName. " +
|
||||
"Please remove the previous version when upgrading to a new version.")
|
||||
}
|
||||
|
||||
cordappClasses[registeredClassName] = registeredCordapps + cordapp
|
||||
}
|
||||
}
|
||||
|
||||
private fun insideInMemoryTest(): Boolean {
|
||||
return Exception().stackTrace.any {
|
||||
it.className.startsWith("net.corda.testing.node.internal.InternalMockNetwork") ||
|
||||
it.className.startsWith("net.corda.testing.node.internal.InProcessNode") ||
|
||||
it.className.startsWith("net.corda.testing.node.MockServices")
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This should only be used when making a change that would break compatibility with existing CorDapps. The change
|
||||
* can then be version-gated, meaning the old behaviour is used if the calling CorDapp's target version is lower
|
||||
* than the platform version that introduces the new behaviour.
|
||||
* In situations where a `[CordappProvider]` is available the CorDapp context should be obtained from there.
|
||||
*
|
||||
* @return Information about the CorDapp from which the invoker is called, null if called outside a CorDapp or the
|
||||
* calling CorDapp cannot be reliably determined.
|
||||
*/
|
||||
val currentCordapp: Cordapp? get() = cordappResolver()
|
||||
|
||||
/**
|
||||
* Returns the target version of the current calling CorDapp. Defaults to platform version 1 if there isn't one,
|
||||
* assuming only basic platform capabilities.
|
||||
*/
|
||||
val currentTargetVersion: Int get() = currentCordapp?.targetPlatformVersion ?: 1
|
||||
|
||||
// A list of extra CorDapps added to the current CorDapps list for testing purposes.
|
||||
private var extraCordappsForTesting = listOf<Cordapp>()
|
||||
|
||||
/**
|
||||
* Return all the CorDapps that were involved in the call stack at the point the provided exception was generated.
|
||||
*
|
||||
* This is provided to allow splitting the cost of generating the exception and retrieving the CorDapps involved.
|
||||
*/
|
||||
fun cordappsFromException(exception: Exception): List<Cordapp> {
|
||||
val apps = exception.stackTrace
|
||||
.mapNotNull { cordappClasses[it.className] }
|
||||
.flatten()
|
||||
.distinct()
|
||||
return (apps + extraCordappsForTesting)
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporarily apply a fake CorDapp with the given parameters. For use in testing.
|
||||
*/
|
||||
@Synchronized
|
||||
@VisibleForTesting
|
||||
fun <T> withTestCordapp(minimumPlatformVersion: Int = 1,
|
||||
targetPlatformVersion: Int = PLATFORM_VERSION,
|
||||
extraApps: List<CordappImpl> = listOf(),
|
||||
block: () -> T): T {
|
||||
val currentResolver = cordappResolver
|
||||
cordappResolver = {
|
||||
CordappImpl.TEST_INSTANCE.copy(minimumPlatformVersion = minimumPlatformVersion, targetPlatformVersion = targetPlatformVersion)
|
||||
}
|
||||
extraCordappsForTesting = listOf(cordappResolver()!!) + extraApps
|
||||
try {
|
||||
return block()
|
||||
} finally {
|
||||
cordappResolver = currentResolver
|
||||
extraCordappsForTesting = listOf()
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
internal fun clear() {
|
||||
cordappClasses.clear()
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
@file:JvmName("Observables")
|
||||
package net.corda.core.observable
|
||||
|
||||
import net.corda.core.observable.internal.OnResilientSubscribe
|
||||
import rx.Observable
|
||||
|
||||
/**
|
||||
* [Observable.continueOnError] is used to return an Observable, through which we can subscribe non unsubscribing [rx.Observer]s
|
||||
* to the source [Observable]. Namely, it makes the [rx.Observer]s resilient to exceptions coming out of [rx.Observer.onNext].
|
||||
*
|
||||
* [Observable.continueOnError] should be called before every subscribe to have the aforementioned effect.
|
||||
*/
|
||||
fun <T> Observable<T>.continueOnError(): Observable<T> = Observable.unsafeCreate(OnResilientSubscribe(this, true))
|
@ -0,0 +1,120 @@
|
||||
package net.corda.core.observable.internal
|
||||
|
||||
import net.corda.core.internal.VisibleForTesting
|
||||
import rx.Observable
|
||||
import rx.Observer
|
||||
import rx.Subscriber
|
||||
import rx.exceptions.CompositeException
|
||||
import rx.exceptions.Exceptions
|
||||
import rx.exceptions.OnErrorFailedException
|
||||
import rx.exceptions.OnErrorNotImplementedException
|
||||
import rx.internal.util.ActionSubscriber
|
||||
import rx.observers.SafeSubscriber
|
||||
import rx.plugins.RxJavaHooks
|
||||
import rx.plugins.RxJavaPlugins
|
||||
import rx.subjects.Subject
|
||||
|
||||
/**
|
||||
* Extends [SafeSubscriber] to override [SafeSubscriber.onNext], [SafeSubscriber.onError] and [SafeSubscriber._onError].
|
||||
*
|
||||
* [ResilientSubscriber] will not set [SafeSubscriber.done] flag to true nor will call [SafeSubscriber.unsubscribe] upon
|
||||
* error inside [Observer.onNext]. This way, the [ResilientSubscriber] will not get unsubscribed and therefore the underlying [Observer]
|
||||
* will not get removed.
|
||||
*
|
||||
* An [Observer] that will not get removed due to errors in [onNext] events becomes useful when an unsubscribe could
|
||||
* lead to a malfunctioning CorDapp, due to a single isolated error. If the [Observer] gets removed,
|
||||
* it will no longer be available the next time any events are pushed from the base [Subject].
|
||||
*/
|
||||
@VisibleForTesting
|
||||
class ResilientSubscriber<T>(actual: Subscriber<in T>) : SafeSubscriber<T>(actual) {
|
||||
|
||||
/**
|
||||
* Duplicate of [SafeSubscriber.onNext]. However, it ignores [SafeSubscriber.done] flag.
|
||||
* It only delegates to [SafeSubscriber.onError] if it wraps an [ActionSubscriber] which is
|
||||
* a leaf in an Subscribers' tree structure.
|
||||
*/
|
||||
@Suppress("TooGenericExceptionCaught")
|
||||
override fun onNext(t: T) {
|
||||
try {
|
||||
actual.onNext(t)
|
||||
} catch (e: Throwable) {
|
||||
if (actual is ActionSubscriber) {
|
||||
// this Subscriber wraps an ActionSubscriber which is always a leaf Observer, then call user-defined onError
|
||||
Exceptions.throwOrReport(e, this)
|
||||
} else {
|
||||
// this Subscriber may wrap a non leaf Observer. In case the wrapped Observer is a PublishSubject then we
|
||||
// should not call onError because PublishSubjectState.onError will shut down all of the Observers under it
|
||||
throw OnNextFailedException(
|
||||
"Observer.onNext failed, this is a non leaf ResilientSubscriber, therefore onError will be skipped", e
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate of [SafeSubscriber.onError]. However, it will not set [SafeSubscriber.done] flag to true.
|
||||
*/
|
||||
override fun onError(e: Throwable) {
|
||||
Exceptions.throwIfFatal(e)
|
||||
_onError(e)
|
||||
}
|
||||
|
||||
/**
|
||||
* Duplicate of [SafeSubscriber._onError]. However, it will not call [Subscriber.unsubscribe].
|
||||
*/
|
||||
@Suppress("TooGenericExceptionCaught")
|
||||
override fun _onError(e: Throwable) {
|
||||
@Suppress("DEPRECATION")
|
||||
RxJavaPlugins.getInstance().errorHandler.handleError(e)
|
||||
try {
|
||||
actual.onError(e)
|
||||
} catch (e: OnErrorNotImplementedException) {
|
||||
throw e
|
||||
} catch (e2: Throwable) {
|
||||
RxJavaHooks.onError(e2)
|
||||
throw OnErrorFailedException(
|
||||
"Error occurred when trying to propagate error to Observer.onError", CompositeException(listOf(e, e2))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We throw [OnNextFailedException] to pass the exception back through the preceding [Subscriber] chain
|
||||
* without triggering any [SafeSubscriber.onError]s. Since we are extending an [OnErrorNotImplementedException]
|
||||
* the exception will be re-thrown at [Exceptions.throwOrReport].
|
||||
*/
|
||||
@VisibleForTesting
|
||||
class OnNextFailedException(message: String, cause: Throwable) : OnErrorNotImplementedException(message, cause)
|
||||
|
||||
/**
|
||||
* [OnResilientSubscribe] returns an [Observable] holding a reference to the source [Observable]. Upon subscribing to it,
|
||||
* when reaching [call] method, if the subscriber passed in [isSafeSubscriber] it will unwrap the [Observer] from
|
||||
* the [SafeSubscriber], re-wrap it with [ResilientSubscriber] and then subscribe it to the source [Observable].
|
||||
*
|
||||
* In case we need to subscribe with a [SafeSubscriber] to the source [Observable] via [OnResilientSubscribe], we have to:
|
||||
* 1. Declare a custom SafeSubscriber extending [SafeSubscriber].
|
||||
* 2. Wrap our [rx.Observer] -to be subscribed to the source [Observable]- with the custom SafeSubscriber.
|
||||
* 3. Create a [OnResilientSubscribe] object with [strictMode] = false.
|
||||
* 3. Call [Observable.unsafeCreate] passing in as argument the [OnResilientSubscribe].
|
||||
* 4. Subscribe to the returned [Observable] passing in as argument the custom SafeSubscriber.
|
||||
*/
|
||||
class OnResilientSubscribe<T>(val source: Observable<T>, private val strictMode: Boolean): Observable.OnSubscribe<T> {
|
||||
|
||||
override fun call(subscriber: Subscriber<in T>) {
|
||||
if (isSafeSubscriber(subscriber)) {
|
||||
source.unsafeSubscribe(ResilientSubscriber((subscriber as SafeSubscriber).actual))
|
||||
} else {
|
||||
source.unsafeSubscribe(subscriber)
|
||||
}
|
||||
}
|
||||
|
||||
private fun isSafeSubscriber(subscriber: Subscriber<*>): Boolean {
|
||||
return if (strictMode) {
|
||||
// In strictMode mode we capture SafeSubscriber subclasses as well
|
||||
SafeSubscriber::class.java.isAssignableFrom(subscriber::class.java)
|
||||
} else {
|
||||
subscriber::class == SafeSubscriber::class
|
||||
}
|
||||
}
|
||||
}
|
@ -664,7 +664,7 @@ class CryptoUtilsTest {
|
||||
assertFalse(Crypto.publicKeyOnCurve(EDDSA_ED25519_SHA512, EdDSAPublicKey(pubKeySpec)))
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException::class)
|
||||
@Test(expected = IllegalArgumentException::class, timeout = 300_000)
|
||||
fun `Unsupported EC public key type on curve`() {
|
||||
val keyGen = KeyPairGenerator.getInstance("EC") // sun.security.ec.ECPublicKeyImpl
|
||||
keyGen.initialize(256, newSecureRandom())
|
||||
|
@ -69,7 +69,7 @@ class ClassLoadingUtilsTest {
|
||||
.doesNotContain(AbstractClass::class.java.name)
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException::class)
|
||||
@Test(expected = IllegalArgumentException::class,timeout=300_000)
|
||||
fun throwsExceptionWhenClassDoesNotContainProperConstructors() {
|
||||
createInstancesOfClassesImplementing(BaseInterface::class.java.classLoader, BaseInterface2::class.java)
|
||||
}
|
||||
|
@ -1,92 +0,0 @@
|
||||
package net.corda.core.internal.cordapp
|
||||
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.assertj.core.api.Assertions.assertThatThrownBy
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import java.lang.IllegalStateException
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class CordappResolverTest {
|
||||
@Before
|
||||
@After
|
||||
fun clearCordappInfoResolver() {
|
||||
CordappResolver.clear()
|
||||
}
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun `the correct cordapp resolver is used after calling withCordappInfo`() {
|
||||
val defaultTargetVersion = 222
|
||||
|
||||
CordappResolver.register(CordappImpl.TEST_INSTANCE.copy(
|
||||
contractClassNames = listOf(javaClass.name),
|
||||
minimumPlatformVersion = 3,
|
||||
targetPlatformVersion = defaultTargetVersion
|
||||
))
|
||||
assertEquals(defaultTargetVersion, CordappResolver.currentTargetVersion)
|
||||
|
||||
val expectedTargetVersion = 555
|
||||
CordappResolver.withTestCordapp(targetPlatformVersion = expectedTargetVersion) {
|
||||
val actualTargetVersion = CordappResolver.currentTargetVersion
|
||||
assertEquals(expectedTargetVersion, actualTargetVersion)
|
||||
}
|
||||
assertEquals(defaultTargetVersion, CordappResolver.currentTargetVersion)
|
||||
}
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun `when the same cordapp is registered for the same class multiple times, the resolver deduplicates and returns it as the current one`() {
|
||||
CordappResolver.register(CordappImpl.TEST_INSTANCE.copy(
|
||||
contractClassNames = listOf(javaClass.name),
|
||||
minimumPlatformVersion = 3,
|
||||
targetPlatformVersion = 222
|
||||
))
|
||||
CordappResolver.register(CordappImpl.TEST_INSTANCE.copy(
|
||||
contractClassNames = listOf(javaClass.name),
|
||||
minimumPlatformVersion = 2,
|
||||
targetPlatformVersion = 456
|
||||
))
|
||||
assertThat(CordappResolver.currentCordapp).isNotNull()
|
||||
}
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun `when different cordapps are registered for the same (non-contract) class, the resolver returns null`() {
|
||||
CordappResolver.register(CordappImpl.TEST_INSTANCE.copy(
|
||||
contractClassNames = listOf("ContractClass1"),
|
||||
minimumPlatformVersion = 3,
|
||||
targetPlatformVersion = 222,
|
||||
jarHash = SecureHash.randomSHA256()
|
||||
))
|
||||
CordappResolver.register(CordappImpl.TEST_INSTANCE.copy(
|
||||
contractClassNames = listOf("ContractClass2"),
|
||||
minimumPlatformVersion = 2,
|
||||
targetPlatformVersion = 456,
|
||||
jarHash = SecureHash.randomSHA256()
|
||||
))
|
||||
assertThat(CordappResolver.currentCordapp).isNull()
|
||||
}
|
||||
|
||||
@Test(timeout=300_000)
|
||||
fun `when different cordapps are registered for the same (contract) class, the resolver throws an exception`() {
|
||||
val firstCordapp = CordappImpl.TEST_INSTANCE.copy(
|
||||
contractClassNames = listOf(javaClass.name),
|
||||
minimumPlatformVersion = 3,
|
||||
targetPlatformVersion = 222,
|
||||
jarHash = SecureHash.randomSHA256()
|
||||
)
|
||||
val secondCordapp = CordappImpl.TEST_INSTANCE.copy(
|
||||
contractClassNames = listOf(javaClass.name),
|
||||
minimumPlatformVersion = 2,
|
||||
targetPlatformVersion = 456,
|
||||
jarHash = SecureHash.randomSHA256()
|
||||
)
|
||||
|
||||
CordappResolver.register(firstCordapp)
|
||||
assertThatThrownBy { CordappResolver.register(secondCordapp) }
|
||||
.isInstanceOf(IllegalStateException::class.java)
|
||||
.hasMessageContaining("More than one CorDapp installed on the node for contract ${javaClass.name}. " +
|
||||
"Please remove the previous version when upgrading to a new version.")
|
||||
}
|
||||
|
||||
}
|
@ -1198,7 +1198,7 @@
|
||||
<ID>MagicNumber:X509Utilities.kt$X509Utilities$3650</ID>
|
||||
<ID>MagicNumber:errorAndTerminate.kt$10</ID>
|
||||
<ID>MatchingDeclarationName:AMQPSerializerFactories.kt$net.corda.serialization.internal.amqp.AMQPSerializerFactories.kt</ID>
|
||||
<ID>MatchingDeclarationName:AMQPTestSerialiationScheme.kt$net.corda.node.internal.serialization.testutils.AMQPTestSerialiationScheme.kt</ID>
|
||||
<ID>MatchingDeclarationName:AMQPTestSerialiationScheme.kt$net.corda.nodeapi.internal.serialization.testutils.AMQPTestSerialiationScheme.kt</ID>
|
||||
<ID>MatchingDeclarationName:AttachmentDemo.kt$net.corda.attachmentdemo.AttachmentDemo.kt</ID>
|
||||
<ID>MatchingDeclarationName:AzureRegistryLocator.kt$net.corda.networkbuilder.containers.push.azure.AzureRegistryLocator.kt</ID>
|
||||
<ID>MatchingDeclarationName:CheckpointSerializationScheme.kt$net.corda.serialization.internal.CheckpointSerializationScheme.kt</ID>
|
||||
@ -1656,6 +1656,7 @@
|
||||
<ID>TooGenericExceptionThrown:ClassLoadingUtilsTest.kt$ClassLoadingUtilsTest$throw RuntimeException()</ID>
|
||||
<ID>TooGenericExceptionThrown:CommandParsers.kt$AzureParser.RegionConverter$throw Error("Unknown azure region: $value")</ID>
|
||||
<ID>TooGenericExceptionThrown:ContractHierarchyTest.kt$ContractHierarchyTest.IndirectContractParent$throw RuntimeException("Boom!")</ID>
|
||||
<ID>TooGenericExceptionThrown:CordaRPCClientReconnectionTest.kt$CordaRPCClientReconnectionTest$throw RuntimeException()</ID>
|
||||
<ID>TooGenericExceptionThrown:CrossCashTest.kt$throw Exception( "Generated exit of ${request.amount} from $issuer, however there is no cash to exit!" )</ID>
|
||||
<ID>TooGenericExceptionThrown:CrossCashTest.kt$throw Exception( "Generated payment of ${request.amount} from $issuer, " + "however they only have $issuerQuantity!" )</ID>
|
||||
<ID>TooGenericExceptionThrown:CrossCashTest.kt$throw Exception( "Generated payment of ${request.amount} from ${node.mainIdentity}, " + "however there is no cash from $issuer!" )</ID>
|
||||
@ -1715,7 +1716,7 @@
|
||||
<ID>TooManyFunctions:LedgerTransaction.kt$LedgerTransaction : FullTransaction</ID>
|
||||
<ID>TooManyFunctions:LocalSerializerFactory.kt$DefaultLocalSerializerFactory : LocalSerializerFactory</ID>
|
||||
<ID>TooManyFunctions:LocalTypeInformationBuilder.kt$LocalTypeInformationBuilder</ID>
|
||||
<ID>TooManyFunctions:MockNodeMessagingService.kt$MockNodeMessagingService : SingletonSerializeAsTokenMessagingService</ID>
|
||||
<ID>TooManyFunctions:MockNodeMessagingService.kt$MockNodeMessagingService : SingletonSerializeAsTokenMessagingServiceServiceStateSupport</ID>
|
||||
<ID>TooManyFunctions:NetworkBootstrapper.kt$NetworkBootstrapper : NetworkBootstrapperWithOverridableParameters</ID>
|
||||
<ID>TooManyFunctions:Node.kt$Node : AbstractNode</ID>
|
||||
<ID>TooManyFunctions:NodeAttachmentService.kt$NodeAttachmentService : AttachmentStorageInternalSingletonSerializeAsToken</ID>
|
||||
@ -1724,7 +1725,7 @@
|
||||
<ID>TooManyFunctions:NodeVaultService.kt$NodeVaultService : SingletonSerializeAsTokenVaultServiceInternal</ID>
|
||||
<ID>TooManyFunctions:OGSwapPricingExample.kt$SwapPricingExample</ID>
|
||||
<ID>TooManyFunctions:ObservableUtilities.kt$net.corda.client.jfx.utils.ObservableUtilities.kt</ID>
|
||||
<ID>TooManyFunctions:P2PMessagingClient.kt$P2PMessagingClient : SingletonSerializeAsTokenMessagingServiceAddressToArtemisQueueResolver</ID>
|
||||
<ID>TooManyFunctions:P2PMessagingClient.kt$P2PMessagingClient : SingletonSerializeAsTokenMessagingServiceAddressToArtemisQueueResolverServiceStateSupport</ID>
|
||||
<ID>TooManyFunctions:PathUtils.kt$net.corda.core.internal.PathUtils.kt</ID>
|
||||
<ID>TooManyFunctions:Perceivable.kt$net.corda.finance.contracts.universal.Perceivable.kt</ID>
|
||||
<ID>TooManyFunctions:PersistentIdentityService.kt$PersistentIdentityService : SingletonSerializeAsTokenIdentityServiceInternal</ID>
|
||||
@ -2112,7 +2113,7 @@
|
||||
<ID>WildcardImport:FlowFrameworkTests.kt$import net.corda.testing.node.internal.*</ID>
|
||||
<ID>WildcardImport:FlowFrameworkTripartyTests.kt$import net.corda.testing.node.internal.*</ID>
|
||||
<ID>WildcardImport:FlowLogicRefFactoryImpl.kt$import net.corda.core.flows.*</ID>
|
||||
<ID>WildcardImport:FlowMatchers.kt$import net.corda.testing.internal.matchers.*</ID>
|
||||
<ID>WildcardImport:FlowMatchers.kt$import net.corda.coretesting.internal.matchers.*</ID>
|
||||
<ID>WildcardImport:FlowOverrideTests.kt$import net.corda.core.flows.*</ID>
|
||||
<ID>WildcardImport:FlowRetryTest.kt$import net.corda.core.flows.*</ID>
|
||||
<ID>WildcardImport:FlowStackSnapshotTest.kt$import net.corda.core.flows.*</ID>
|
||||
|
11
detekt-plugins/build.gradle
Normal file
11
detekt-plugins/build.gradle
Normal file
@ -0,0 +1,11 @@
|
||||
plugins {
|
||||
id 'kotlin'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8'
|
||||
implementation "io.gitlab.arturbosch.detekt:detekt-api:$detekt_version"
|
||||
testImplementation "junit:junit:$junit_version"
|
||||
testImplementation "io.gitlab.arturbosch.detekt:detekt-test:$detekt_version"
|
||||
testImplementation "org.assertj:assertj-core:$assertj_version"
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package net.corda.detekt.plugins
|
||||
|
||||
import io.gitlab.arturbosch.detekt.api.Config
|
||||
import io.gitlab.arturbosch.detekt.api.RuleSet
|
||||
import io.gitlab.arturbosch.detekt.api.RuleSetProvider
|
||||
import net.corda.detekt.plugins.rules.TestWithMissingTimeout
|
||||
|
||||
// When adding new detekt rules, add the new rule to the list of instances below.
|
||||
class CordaDetektProvider : RuleSetProvider {
|
||||
|
||||
override val ruleSetId: String = "corda-detekt"
|
||||
|
||||
override fun instance(config: Config): RuleSet = RuleSet(
|
||||
ruleSetId,
|
||||
listOf(
|
||||
TestWithMissingTimeout()
|
||||
)
|
||||
)
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package net.corda.detekt.plugins.rules
|
||||
|
||||
import io.gitlab.arturbosch.detekt.api.CodeSmell
|
||||
import io.gitlab.arturbosch.detekt.api.Debt
|
||||
import io.gitlab.arturbosch.detekt.api.Entity
|
||||
import io.gitlab.arturbosch.detekt.api.Issue
|
||||
import io.gitlab.arturbosch.detekt.api.Rule
|
||||
import io.gitlab.arturbosch.detekt.api.Severity
|
||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
||||
|
||||
class TestWithMissingTimeout : Rule() {
|
||||
|
||||
override val issue = Issue(
|
||||
javaClass.simpleName,
|
||||
Severity.Security,
|
||||
"This rule reports a test case with a missing timeout field in the @Test annotation",
|
||||
Debt.FIVE_MINS
|
||||
)
|
||||
|
||||
// Checks that the test is using JUnit 4 by looking at the imports in the file. This is a little questionable, but this information is
|
||||
// otherwise not exposed.
|
||||
private fun isTestAnnotationJunit4(annotationEntry: KtAnnotationEntry): Boolean {
|
||||
return annotationEntry.containingKtFile.importDirectives.any { it.importPath?.fqName?.asString() == "org.junit.Test" }
|
||||
}
|
||||
|
||||
// Look at all annotations. If they are named "Test", and the corresponding file has a JUnit 4 Test import in, assume that all these
|
||||
// annotations are JUnit Tests and report if they do not have a "timeout" argument.
|
||||
// Note that this doesn't apply to JUnit 5 as the test annotation does not take a timeout argument in this case.
|
||||
override fun visitAnnotationEntry(annotationEntry: KtAnnotationEntry) {
|
||||
if (annotationEntry.shortName.toString() == "Test" && isTestAnnotationJunit4(annotationEntry)) {
|
||||
val params = annotationEntry.valueArguments
|
||||
if (params.none { it.getArgumentName()?.asName?.identifier == "timeout" }) {
|
||||
report(CodeSmell(issue, Entity.from(annotationEntry), "Missing timeout parameter from Test annotation"))
|
||||
}
|
||||
}
|
||||
super.visitAnnotationEntry(annotationEntry)
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
net.corda.detekt.plugins.CordaDetektProvider
|
@ -0,0 +1,77 @@
|
||||
package net.corda.detekt.plugins.rules
|
||||
|
||||
import io.gitlab.arturbosch.detekt.test.assertThat
|
||||
import io.gitlab.arturbosch.detekt.test.lint
|
||||
import org.junit.Test
|
||||
|
||||
class TestWithMissingTimeoutTest {
|
||||
|
||||
private val junit4Code = """
|
||||
import org.junit.Test
|
||||
import org.junit.Assert
|
||||
|
||||
class JUnit4Test {
|
||||
@Test
|
||||
@Ignore
|
||||
fun `test that foo is not bar`() {
|
||||
Assert.assertFalse("foo" == "bar")
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
private val junit5Code = """
|
||||
package net.corda.serialization.djvm
|
||||
|
||||
import net.corda.core.serialization.internal._contextSerializationEnv
|
||||
import net.corda.core.serialization.serialize
|
||||
import net.corda.serialization.djvm.SandboxType.KOTLIN
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import org.junit.jupiter.api.fail
|
||||
import java.time.Instant
|
||||
import java.util.function.Function
|
||||
|
||||
@ExtendWith(LocalSerialization::class)
|
||||
class DeserializeInstantTest : TestBase(KOTLIN) {
|
||||
@Test
|
||||
fun `test deserializing instant`() {
|
||||
val instant = Instant.now()
|
||||
val data = instant.serialize()
|
||||
|
||||
sandbox {
|
||||
_contextSerializationEnv.set(createSandboxSerializationEnv(classLoader))
|
||||
|
||||
val sandboxInstant = data.deserializeFor(classLoader)
|
||||
|
||||
val taskFactory = classLoader.createRawTaskFactory()
|
||||
val showInstant = taskFactory.compose(classLoader.createSandboxFunction()).apply(ShowInstant::class.java)
|
||||
val result = showInstant.apply(sandboxInstant) ?: fail("Result cannot be null")
|
||||
|
||||
assertEquals(instant.toString(), result.toString())
|
||||
assertEquals(SANDBOX_STRING, result::class.java.name)
|
||||
}
|
||||
}
|
||||
|
||||
class ShowInstant : Function<Instant, String> {
|
||||
override fun apply(instant: Instant): String {
|
||||
return instant.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
|
||||
@Test(timeout = 300_000)
|
||||
fun `catches missing timeout for junit 4 tests`() {
|
||||
val rule = TestWithMissingTimeout()
|
||||
val findings = rule.lint(junit4Code)
|
||||
assertThat(findings).hasSize(1)
|
||||
}
|
||||
|
||||
@Test(timeout = 300_000)
|
||||
fun `does not warn for junit 5 tests`() {
|
||||
val rule = TestWithMissingTimeout()
|
||||
val findings = rule.lint(junit5Code)
|
||||
assertThat(findings).hasSize(0)
|
||||
}
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
NODE_LIST=("dockerNode1" "dockerNode2" "dockerNode3")
|
||||
NETWORK_NAME=mininet
|
||||
CORDAPP_VERSION="4.4-SNAPSHOT"
|
||||
DOCKER_IMAGE_VERSION="corda-zulu-4.4-snapshot"
|
||||
CORDAPP_VERSION="4.5-SNAPSHOT"
|
||||
DOCKER_IMAGE_VERSION="corda-zulu-4.5-snapshot"
|
||||
|
||||
mkdir cordapps
|
||||
rm -f cordapps/*
|
||||
|
@ -1,19 +1,23 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
GENERATE_TEST_NET=0
|
||||
GENERATE_GENERIC=0
|
||||
EXIT_ON_GENERATE=0
|
||||
|
||||
die() {
|
||||
printf '%s\n' "$1" >&2
|
||||
exit 1
|
||||
printf '%s\n' "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
show_help(){
|
||||
echo "usage: generate-config <--testnet>|<--generic>"
|
||||
echo -e "\t --testnet is used to generate config and certificates for joining TestNet"
|
||||
echo -e "\t --generic is used to generate config and certificates for joining an existing Corda Compatibility Zone"
|
||||
show_help() {
|
||||
echo "usage: generate-config <--testnet>|<--generic>"
|
||||
echo -e "\t --testnet is used to generate config and certificates for joining TestNet"
|
||||
echo -e "\t --generic is used to generate config and certificates for joining an existing Corda Compatibility Zone"
|
||||
}
|
||||
|
||||
function generateTestnetConfig() {
|
||||
: ${RPC_PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)}
|
||||
RPC_PASSWORD=${RPC_PASSWORD} \
|
||||
: ${RPC_PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)}
|
||||
RPC_PASSWORD=${RPC_PASSWORD} \
|
||||
DB_PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) \
|
||||
MY_PUBLIC_ADDRESS=${MY_PUBLIC_ADDRESS} \
|
||||
MY_P2P_PORT=${MY_P2P_PORT} \
|
||||
@ -24,101 +28,105 @@ function generateTestnetConfig() {
|
||||
java -jar config-exporter.jar "TEST-NET-COMBINE" "node.conf" "/opt/corda/starting-node.conf" "${CONFIG_FOLDER}/node.conf"
|
||||
}
|
||||
|
||||
function generateGenericCZConfig(){
|
||||
if ! [[ -f ${CONFIG_FOLDER}/node.conf ]] ; then
|
||||
echo 'INFO: no existing node config detected, generating config skeleton'
|
||||
: ${NETWORKMAP_URL:? '$NETWORKMAP_URL, the Compatibility Zone to join must be set as environment variable'}
|
||||
: ${DOORMAN_URL:? '$DOORMAN_URL, the Doorman to use when joining must be set as environment variable'}
|
||||
: ${MY_LEGAL_NAME:? '$MY_LEGAL_NAME, the X500 name to use when joining must be set as environment variable'}
|
||||
: ${MY_EMAIL_ADDRESS:? '$MY_EMAIL_ADDRESS, the email to use when joining must be set as an environment variable'}
|
||||
: ${NETWORK_TRUST_PASSWORD=:? '$NETWORK_TRUST_PASSWORD, the password to the network store to use when joining must be set as environment variable'}
|
||||
function generateGenericCZConfig() {
|
||||
if ! [[ -f ${CONFIG_FOLDER}/node.conf ]]; then
|
||||
echo 'INFO: no existing node config detected, generating config skeleton'
|
||||
: ${NETWORKMAP_URL:? '$NETWORKMAP_URL, the Compatibility Zone to join must be set as environment variable'}
|
||||
: ${DOORMAN_URL:? '$DOORMAN_URL, the Doorman to use when joining must be set as environment variable'}
|
||||
: ${MY_LEGAL_NAME:? '$MY_LEGAL_NAME, the X500 name to use when joining must be set as environment variable'}
|
||||
: ${MY_EMAIL_ADDRESS:? '$MY_EMAIL_ADDRESS, the email to use when joining must be set as an environment variable'}
|
||||
: ${NETWORK_TRUST_PASSWORD=:? '$NETWORK_TRUST_PASSWORD, the password to the network store to use when joining must be set as environment variable'}
|
||||
|
||||
if [[ ! -f ${CERTIFICATES_FOLDER}/${TRUST_STORE_NAME} ]]; then
|
||||
die "Network Trust Root file not found"
|
||||
fi
|
||||
: ${RPC_PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)}
|
||||
RPC_PASSWORD=${RPC_PASSWORD} \
|
||||
DB_PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) \
|
||||
MY_PUBLIC_ADDRESS=${MY_PUBLIC_ADDRESS} \
|
||||
MY_P2P_PORT=${MY_P2P_PORT} \
|
||||
MY_RPC_PORT=${MY_RPC_PORT} \
|
||||
MY_RPC_ADMIN_PORT=${MY_RPC_ADMIN_PORT} \
|
||||
java -jar config-exporter.jar "GENERIC-CZ" "/opt/corda/starting-node.conf" "${CONFIG_FOLDER}/node.conf"
|
||||
if [[ ! -f ${CERTIFICATES_FOLDER}/${TRUST_STORE_NAME} ]]; then
|
||||
die "Network Trust Root file not found"
|
||||
fi
|
||||
: ${RPC_PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)}
|
||||
RPC_PASSWORD=${RPC_PASSWORD} \
|
||||
DB_PASSWORD=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1) \
|
||||
MY_PUBLIC_ADDRESS=${MY_PUBLIC_ADDRESS} \
|
||||
MY_P2P_PORT=${MY_P2P_PORT} \
|
||||
MY_RPC_PORT=${MY_RPC_PORT} \
|
||||
MY_RPC_ADMIN_PORT=${MY_RPC_ADMIN_PORT} \
|
||||
java -jar config-exporter.jar "GENERIC-CZ" "/opt/corda/starting-node.conf" "${CONFIG_FOLDER}/node.conf"
|
||||
fi
|
||||
java -Djava.security.egd=file:/dev/./urandom -Dcapsule.jvm.args="${JVM_ARGS}" -jar /opt/corda/bin/corda.jar \
|
||||
--initial-registration \
|
||||
--base-directory /opt/corda \
|
||||
--config-file ${CONFIG_FOLDER}/node.conf \
|
||||
--network-root-truststore-password ${NETWORK_TRUST_PASSWORD} \
|
||||
--network-root-truststore ${CERTIFICATES_FOLDER}/${TRUST_STORE_NAME} &&
|
||||
echo "Successfully registered with ${DOORMAN_URL}, starting corda"
|
||||
if [[ ${EXIT_ON_GENERATE} == 1 ]]; then
|
||||
exit 0
|
||||
else
|
||||
run-corda
|
||||
fi
|
||||
java -Djava.security.egd=file:/dev/./urandom -Dcapsule.jvm.args="${JVM_ARGS}" -jar /opt/corda/bin/corda.jar \
|
||||
--initial-registration \
|
||||
--base-directory /opt/corda \
|
||||
--config-file ${CONFIG_FOLDER}/node.conf \
|
||||
--network-root-truststore-password ${NETWORK_TRUST_PASSWORD} \
|
||||
--network-root-truststore ${CERTIFICATES_FOLDER}/${TRUST_STORE_NAME} && \
|
||||
echo "Successfully registered with ${DOORMAN_URL}, starting corda" && \
|
||||
run-corda
|
||||
}
|
||||
|
||||
function downloadTestnetCerts() {
|
||||
if [[ ! -f ${CERTIFICATES_FOLDER}/certs.zip ]]; then
|
||||
: ${ONE_TIME_DOWNLOAD_KEY:? '$ONE_TIME_DOWNLOAD_KEY must be set as environment variable'}
|
||||
: ${LOCALITY:? '$LOCALITY (the locality used when registering for Testnet) must be set as environment variable'}
|
||||
: ${COUNTRY:? '$COUNTRY (the country used when registering for Testnet) must be set as environment variable'}
|
||||
curl \
|
||||
-X POST "https://onboarder.prod.ws.r3.com/api/user/node/generate/one-time-key/redeem/$ONE_TIME_DOWNLOAD_KEY" \
|
||||
-o "${CERTIFICATES_FOLDER}/certs.zip"
|
||||
fi
|
||||
rm -rf ${CERTIFICATES_FOLDER}/*.jks
|
||||
unzip ${CERTIFICATES_FOLDER}/certs.zip
|
||||
if [[ ! -f ${CERTIFICATES_FOLDER}/certs.zip ]]; then
|
||||
: ${ONE_TIME_DOWNLOAD_KEY:? '$ONE_TIME_DOWNLOAD_KEY must be set as environment variable'}
|
||||
: ${LOCALITY:? '$LOCALITY (the locality used when registering for Testnet) must be set as environment variable'}
|
||||
: ${COUNTRY:? '$COUNTRY (the country used when registering for Testnet) must be set as environment variable'}
|
||||
curl \
|
||||
-X POST "https://onboarder.prod.ws.r3.com/api/user/node/generate/one-time-key/redeem/$ONE_TIME_DOWNLOAD_KEY" \
|
||||
-o "${CERTIFICATES_FOLDER}/certs.zip"
|
||||
fi
|
||||
rm -rf ${CERTIFICATES_FOLDER}/*.jks
|
||||
unzip ${CERTIFICATES_FOLDER}/certs.zip
|
||||
}
|
||||
|
||||
GENERATE_TEST_NET=0
|
||||
GENERATE_GENERIC=0
|
||||
|
||||
while :; do
|
||||
case $1 in
|
||||
-h|-\?|--help)
|
||||
show_help # Display a usage synopsis.
|
||||
exit
|
||||
;;
|
||||
-t|--testnet)
|
||||
if [[ ${GENERATE_GENERIC} = 0 ]]; then
|
||||
GENERATE_TEST_NET=1
|
||||
else
|
||||
die 'ERROR: cannot generate config for multiple networks'
|
||||
fi
|
||||
;;
|
||||
-g|--generic)
|
||||
if [[ ${GENERATE_TEST_NET} = 0 ]]; then
|
||||
GENERATE_GENERIC=1
|
||||
else
|
||||
die 'ERROR: cannot generate config for multiple networks'
|
||||
fi
|
||||
;;
|
||||
--) # End of all options.
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-?*)
|
||||
printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2
|
||||
;;
|
||||
*) # Default case: No more options, so break out of the loop.
|
||||
break
|
||||
esac
|
||||
case $1 in
|
||||
-h | -\? | --help)
|
||||
show_help # Display a usage synopsis.
|
||||
exit
|
||||
;;
|
||||
-t | --testnet)
|
||||
if [[ ${GENERATE_GENERIC} == 0 ]]; then
|
||||
GENERATE_TEST_NET=1
|
||||
else
|
||||
die 'ERROR: cannot generate config for multiple networks'
|
||||
fi
|
||||
;;
|
||||
-g | --generic)
|
||||
if [[ ${GENERATE_TEST_NET} == 0 ]]; then
|
||||
GENERATE_GENERIC=1
|
||||
else
|
||||
die 'ERROR: cannot generate config for multiple networks'
|
||||
fi
|
||||
;;
|
||||
-e | --exit-on-generate)
|
||||
if [[ ${EXIT_ON_GENERATE} == 0 ]]; then
|
||||
EXIT_ON_GENERATE=1
|
||||
else
|
||||
die 'ERROR: cannot set exit on generate flag'
|
||||
fi
|
||||
;;
|
||||
--) # End of all options.
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-?*)
|
||||
printf 'WARN: Unknown option (ignored): %s\n' "$1" >&2
|
||||
;;
|
||||
*) # Default case: No more options, so break out of the loop.
|
||||
break ;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
: ${TRUST_STORE_NAME="network-root-truststore.jks"}
|
||||
: ${JVM_ARGS='-Xmx4g -Xms2g -XX:+UseG1GC'}
|
||||
|
||||
|
||||
if [[ ${GENERATE_TEST_NET} == 1 ]]
|
||||
then
|
||||
: ${MY_PUBLIC_ADDRESS:? 'MY_PUBLIC_ADDRESS must be set as environment variable'}
|
||||
downloadTestnetCerts
|
||||
generateTestnetConfig
|
||||
elif [[ ${GENERATE_GENERIC} == 1 ]]
|
||||
then
|
||||
: ${MY_PUBLIC_ADDRESS:? 'MY_PUBLIC_ADDRESS must be set as environment variable'}
|
||||
generateGenericCZConfig
|
||||
if [[ ${GENERATE_TEST_NET} == 1 ]]; then
|
||||
: ${MY_PUBLIC_ADDRESS:? 'MY_PUBLIC_ADDRESS must be set as environment variable'}
|
||||
downloadTestnetCerts
|
||||
generateTestnetConfig
|
||||
elif [[ ${GENERATE_GENERIC} == 1 ]]; then
|
||||
: ${MY_PUBLIC_ADDRESS:? 'MY_PUBLIC_ADDRESS must be set as environment variable'}
|
||||
generateGenericCZConfig
|
||||
else
|
||||
show_help
|
||||
die "No Valid Configuration requested"
|
||||
show_help
|
||||
die "No Valid Configuration requested"
|
||||
fi
|
||||
|
||||
|
@ -92,55 +92,73 @@ Corda utility classes, providing a broad range of functionality to help implemen
|
||||
Some simple testing utilities like pre-defined top-level values for common currencies. Mostly useful for
|
||||
writing unit tests in Kotlin.
|
||||
|
||||
WARNING: NOT API STABLE.
|
||||
__WARNING:__ This library is not suitable for production use and should not be used in real CorDapps.
|
||||
Instead, use the [Token SDK](https://github.com/corda/token-sdk), or implement your own library. This
|
||||
library may be removed in a future release without warning.
|
||||
|
||||
# Package net.corda.finance.utils
|
||||
|
||||
A collection of utilities for summing financial states, for example, summing obligations to get total debts.
|
||||
|
||||
WARNING: NOT API STABLE.
|
||||
__WARNING:__ This library is not suitable for production use and should not be used in real CorDapps.
|
||||
Instead, use the [Token SDK](https://github.com/corda/token-sdk), or implement your own library. This
|
||||
library may be removed in a future release without warning.
|
||||
|
||||
# Package net.corda.finance.contracts
|
||||
|
||||
Various types for common financial concepts like day roll conventions, fixes, etc.
|
||||
|
||||
WARNING: NOT API STABLE.
|
||||
__WARNING:__ This library is not suitable for production use and should not be used in real CorDapps.
|
||||
Instead, use the [Token SDK](https://github.com/corda/token-sdk), or implement your own library. This
|
||||
library may be removed in a future release without warning.
|
||||
|
||||
# Package net.corda.finance.contracts.asset
|
||||
|
||||
Cash states, obligations and commodities.
|
||||
|
||||
WARNING: NOT API STABLE.
|
||||
__WARNING:__ This library is not suitable for production use and should not be used in real CorDapps.
|
||||
Instead, use the [Token SDK](https://github.com/corda/token-sdk), or implement your own library. This
|
||||
library may be removed in a future release without warning.
|
||||
|
||||
# Package net.corda.finance.contracts.asset.cash.selection
|
||||
|
||||
Provisional support for pluggable cash selectors, needed for different database backends.
|
||||
|
||||
WARNING: NOT API STABLE.
|
||||
__WARNING:__ This library is not suitable for production use and should not be used in real CorDapps.
|
||||
Instead, use the [Token SDK](https://github.com/corda/token-sdk), or implement your own library. This
|
||||
library may be removed in a future release without warning.
|
||||
|
||||
# Package net.corda.finance.contracts.math
|
||||
|
||||
Splines and interpolation.
|
||||
|
||||
WARNING: NOT API STABLE.
|
||||
__WARNING:__ This library is not suitable for production use and should not be used in real CorDapps.
|
||||
Instead, use the [Token SDK](https://github.com/corda/token-sdk), or implement your own library. This
|
||||
library may be removed in a future release without warning.
|
||||
|
||||
# Package net.corda.finance.flows
|
||||
|
||||
Cash payments and issuances. Two party "delivery vs payment" atomic asset swaps.
|
||||
|
||||
WARNING: NOT API STABLE.
|
||||
__WARNING:__ This library is not suitable for production use and should not be used in real CorDapps.
|
||||
Instead, use the [Token SDK](https://github.com/corda/token-sdk), or implement your own library. This
|
||||
library may be removed in a future release without warning.
|
||||
|
||||
# Package net.corda.finance.plugin
|
||||
|
||||
JSON/Jackson plugin for business calendars.
|
||||
|
||||
WARNING: NOT API STABLE.
|
||||
__WARNING:__ This library is not suitable for production use and should not be used in real CorDapps.
|
||||
Instead, use the [Token SDK](https://github.com/corda/token-sdk), or implement your own library. This
|
||||
library may be removed in a future release without warning.
|
||||
|
||||
# Package net.corda.finance.schemas
|
||||
|
||||
JPA (Java Persistence Architecture) schemas for the financial state types.
|
||||
|
||||
WARNING: NOT API STABLE.
|
||||
__WARNING:__ This library is not suitable for production use and should not be used in real CorDapps.
|
||||
Instead, use the [Token SDK](https://github.com/corda/token-sdk), or implement your own library. This
|
||||
library may be removed in a future release without warning.
|
||||
|
||||
# Package net.corda.testing.core
|
||||
|
||||
|
@ -12,6 +12,9 @@ API: Contract Constraints
|
||||
|
||||
.. note:: Before reading this page, you should be familiar with the key concepts of :doc:`key-concepts-contracts`.
|
||||
|
||||
.. note:: As of Corda |corda_version| the `minimumPlatformVersion` required to use these features is 4
|
||||
(see :ref:`Network Parameters <network-parameters>` and :doc:`features-versions` for more details).
|
||||
|
||||
.. contents::
|
||||
|
||||
Reasons for Contract Constraints
|
||||
|
@ -215,7 +215,7 @@ Remember that a transaction generally needs a notary to:
|
||||
* Prevent double-spends if the transaction has inputs
|
||||
* Serve as a timestamping authority if the transaction has a time-window
|
||||
|
||||
There are several ways to retrieve a notary from the network map:
|
||||
A notary can be retrieved from the network map as follows:
|
||||
|
||||
.. container:: codeset
|
||||
|
||||
@ -264,14 +264,18 @@ In order to create a communication session between your initiator flow and the r
|
||||
* ``sendAndReceive(receiveType: Class<R>, payload: Any): R``
|
||||
* Sends the ``payload`` object and receives an object of type ``receiveType`` back
|
||||
|
||||
In addition ``FlowLogic`` provides functions that batch receives:
|
||||
In addition ``FlowLogic`` provides functions that can receive messages from multiple sessions and send messages to multiple sessions:
|
||||
|
||||
* ``receiveAllMap(sessions: Map<FlowSession, Class<out Any>>): Map<FlowSession, UntrustworthyData<Any>>``
|
||||
Receives from all ``FlowSession`` objects specified in the passed in map. The received types may differ.
|
||||
* Receives from all ``FlowSession`` objects specified in the passed in map. The received types may differ.
|
||||
* ``receiveAll(receiveType: Class<R>, sessions: List<FlowSession>): List<UntrustworthyData<R>>``
|
||||
Receives from all ``FlowSession`` objects specified in the passed in list. The received types must be the same.
|
||||
* Receives from all ``FlowSession`` objects specified in the passed in list. The received types must be the same.
|
||||
* ``sendAll(payload: Any, sessions: Set<FlowSession>)``
|
||||
* Sends the ``payload`` object to all the provided ``FlowSession``\s.
|
||||
* ``sendAll(payloadsPerSession: Map<FlowSession, Any>)``
|
||||
* Sends a potentially different payload to each ``FlowSession``, as specified by the provided ``payloadsPerSession``.
|
||||
|
||||
The batched functions are implemented more efficiently by the flow framework.
|
||||
.. note:: It's more efficient to call ``sendAndReceive`` instead of calling ``send`` and then ``receive``. It's also more efficient to call ``sendAll``/``receiveAll`` instead of multiple ``send``/``receive`` respectively.
|
||||
|
||||
InitiateFlow
|
||||
~~~~~~~~~~~~
|
||||
|
@ -460,6 +460,7 @@ Please note that suspendable flow operations such as:
|
||||
* ``FlowSession.send``
|
||||
* ``FlowSession.receive``
|
||||
* ``FlowLogic.receiveAll``
|
||||
* ``FlowLogic.sendAll``
|
||||
* ``FlowLogic.sleep``
|
||||
* ``FlowLogic.subFlow``
|
||||
|
||||
|
@ -109,6 +109,8 @@ Unreleased
|
||||
options, as well as ``extensions.sshd`` configuration entry, have been removed from the standalone shell.
|
||||
Available alternatives are either to use the standalone shell directly, or connect to the node embedded shell via SSH.
|
||||
|
||||
* Added new node configuration option to exclude packages from Quasar instrumentation.
|
||||
|
||||
.. _changelog_v4.1:
|
||||
|
||||
Version 4.1
|
||||
|
@ -106,6 +106,9 @@ overridden via:
|
||||
|
||||
Limitations
|
||||
```````````
|
||||
* Please note that to limit external connections to your node please use loopback address 127.0.0.1 instead of
|
||||
localhost for client settings such as p2pAddress; since localhost is translated internally to the physical hostname
|
||||
and can be reached externally.
|
||||
|
||||
* If the same key is overridden by both an environment variable and system property, the system property takes precedence.
|
||||
|
||||
@ -150,6 +153,7 @@ Configuration file fields
|
||||
additionalP2PAddresses
|
||||
An array of additional host:port values, which will be included in the advertised NodeInfo in the network map in addition to the :ref:`p2pAddress <corda_configuration_file_p2pAddress>`.
|
||||
Nodes can use this configuration option to advertise HA endpoints and aliases to external parties.
|
||||
0.0.0.0 is not a valid host setting since each additionalP2PAddress must be an external client address.
|
||||
|
||||
*Default:* empty list
|
||||
|
||||
@ -414,7 +418,8 @@ lazyBridgeStart
|
||||
messagingServerAddress
|
||||
The address of the ArtemisMQ broker instance.
|
||||
If not provided the node will run one locally.
|
||||
|
||||
0.0.0.0 should not be specified since this needs to be a valid client address.
|
||||
|
||||
*Default:* not defined
|
||||
|
||||
messagingServerExternal
|
||||
@ -549,9 +554,23 @@ p2pAddress
|
||||
However, note that the host is the included as the advertised entry in the network map.
|
||||
As a result the value listed here must be **externally accessible when running nodes across a cluster of machines.**
|
||||
If the provided host is unreachable, the node will try to auto-discover its public one.
|
||||
0.0.0.0 is not a valid host setting since p2pAddress must be an external client address.
|
||||
|
||||
|
||||
*Default:* not defined
|
||||
|
||||
quasarExcludePackages
|
||||
A list of packages to exclude from Quasar instrumentation. Wildcards are allowed, for example ``org.xml**``.
|
||||
|
||||
**Important: Do not change unless requested by support.**
|
||||
|
||||
*Default:* empty list
|
||||
|
||||
Example configuration:
|
||||
|
||||
.. parsed-literal::
|
||||
quasarExcludePackages=["org.xml**", "org.yaml**"]
|
||||
|
||||
rpcAddress (deprecated)
|
||||
The address of the RPC system on which RPC requests can be made to the node.
|
||||
If not provided then the node will run without RPC.
|
||||
@ -568,12 +587,13 @@ rpcSettings
|
||||
**Important: The RPC SSL certificate is used by RPC clients to authenticate the connection. The Node operator must provide RPC clients with a truststore containing the certificate they can trust. We advise Node operators to not use the P2P keystore for RPC. The node can be run with the "generate-rpc-ssl-settings" command, which generates a secure keystore and truststore that can be used to secure the RPC connection. You can use this if you have no special requirements.**
|
||||
|
||||
address
|
||||
host and port for the RPC server binding.
|
||||
host and port for the RPC server binding. Specifying 0.0.0.0 (as host) is a convention allowing the host to bind all of it's network interfaces when listening on a socket. By itself 0.0.0.0 is non-routeable. i.e. not a proper address.
|
||||
|
||||
*Default:* not defined
|
||||
|
||||
adminAddress
|
||||
host and port for the RPC admin binding (this is the endpoint that the node process will connect to).
|
||||
this needs to follow the same host rules as address setting (see above)
|
||||
|
||||
*Default:* not defined
|
||||
|
||||
@ -643,7 +663,7 @@ sshd
|
||||
|
||||
systemProperties
|
||||
An optional map of additional system properties to be set when launching via ``corda.jar`` only.
|
||||
Keys and values of the map should be strings. e.g. ``systemProperties = { visualvm.display.name = FooBar }``
|
||||
Keys and values of the map should be strings. e.g. ``systemProperties = { "visualvm.display.name" = FooBar }``
|
||||
|
||||
*Default:* not defined
|
||||
|
||||
|
@ -132,7 +132,7 @@ It is possible to configure the name of the Trust Root file by setting the ``TRU
|
||||
-e MY_EMAIL_ADDRESS="cordauser@r3.com" \
|
||||
-v /home/user/docker/config:/etc/corda \
|
||||
-v /home/user/docker/certificates:/opt/corda/certificates \
|
||||
corda/corda-zulu-java1.8-|corda_version_lower|:latest config-generator --generic
|
||||
corda/corda-zulu-java1.8-|corda_version_lower|:latest config-generator --generic --exit-on-generate
|
||||
|
||||
|
||||
Several environment variables must also be passed to the container to allow it to register:
|
||||
|
@ -1,6 +1,5 @@
|
||||
package net.corda.docs.java.tutorial.test;
|
||||
|
||||
import kotlin.Unit;
|
||||
import net.corda.client.rpc.CordaRPCClient;
|
||||
import net.corda.core.messaging.CordaRPCOps;
|
||||
import net.corda.core.utilities.KotlinUtilsKt;
|
||||
@ -10,24 +9,24 @@ import net.corda.testing.driver.*;
|
||||
import net.corda.testing.node.User;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import static java.util.Collections.singleton;
|
||||
import static java.util.Collections.singletonList;
|
||||
import static net.corda.testing.core.TestConstants.ALICE_NAME;
|
||||
import static net.corda.testing.driver.Driver.driver;
|
||||
import static net.corda.testing.node.internal.InternalTestUtilsKt.cordappWithPackages;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public final class TutorialFlowAsyncOperationTest {
|
||||
public class TutorialFlowAsyncOperationTest {
|
||||
// DOCSTART summingWorks
|
||||
@Test
|
||||
public final void summingWorks() {
|
||||
Driver.driver(new DriverParameters(), (DriverDSL dsl) -> {
|
||||
User aliceUser = new User("aliceUser", "testPassword1",
|
||||
new HashSet<>(Collections.singletonList(Permissions.all()))
|
||||
);
|
||||
public void summingWorks() {
|
||||
driver(new DriverParameters(singletonList(cordappWithPackages("net.corda.docs.java.tutorial.flowstatemachines"))), (DriverDSL dsl) -> {
|
||||
User aliceUser = new User("aliceUser", "testPassword1", singleton(Permissions.all()));
|
||||
Future<NodeHandle> aliceFuture = dsl.startNode(new NodeParameters()
|
||||
.withProvidedName(ALICE_NAME)
|
||||
.withRpcUsers(Collections.singletonList(aliceUser))
|
||||
.withRpcUsers(singletonList(aliceUser))
|
||||
);
|
||||
NodeHandle alice = KotlinUtilsKt.getOrThrow(aliceFuture, null);
|
||||
CordaRPCClient aliceClient = new CordaRPCClient(alice.getRpcAddress());
|
||||
@ -35,7 +34,7 @@ public final class TutorialFlowAsyncOperationTest {
|
||||
Future<Integer> answerFuture = aliceProxy.startFlowDynamic(ExampleSummingFlow.class).getReturnValue();
|
||||
int answer = KotlinUtilsKt.getOrThrow(answerFuture, null);
|
||||
assertEquals(3, answer);
|
||||
return Unit.INSTANCE;
|
||||
return null;
|
||||
});
|
||||
}
|
||||
// DOCEND summingWorks
|
||||
|
@ -10,7 +10,6 @@ import net.corda.testing.driver.DriverParameters
|
||||
import net.corda.testing.driver.driver
|
||||
import net.corda.testing.node.User
|
||||
import net.corda.testing.node.internal.cordappWithPackages
|
||||
import net.corda.testing.node.internal.findCordapp
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
|
@ -117,19 +117,14 @@ public class FlowCookbook {
|
||||
progressTracker.setCurrentStep(ID_OTHER_NODES);
|
||||
// DOCEND 18
|
||||
|
||||
// A transaction generally needs a notary:
|
||||
// Every transaction needs a notary:
|
||||
// - To prevent double-spends if the transaction has inputs
|
||||
// - To serve as a timestamping authority if the transaction has a
|
||||
// time-window
|
||||
// We retrieve a notary from the network map.
|
||||
// DOCSTART 01
|
||||
CordaX500Name notaryName = new CordaX500Name("Notary Service", "London", "GB");
|
||||
Party specificNotary = getServiceHub().getNetworkMapCache().getNotary(notaryName);
|
||||
// Alternatively, we can pick an arbitrary notary from the notary
|
||||
// list. However, it is always preferable to specify the notary
|
||||
// explicitly, as the notary list might change when new notaries are
|
||||
// introduced, or old ones decommissioned.
|
||||
Party firstNotary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
|
||||
Party notary = getServiceHub().getNetworkMapCache().getNotary(notaryName);
|
||||
// DOCEND 01
|
||||
|
||||
// We may also need to identify a specific counterparty. We do so
|
||||
@ -328,7 +323,7 @@ public class FlowCookbook {
|
||||
// If our transaction has input states or a time-window, we must instantiate it with a
|
||||
// notary.
|
||||
// DOCSTART 19
|
||||
TransactionBuilder txBuilder = new TransactionBuilder(specificNotary);
|
||||
TransactionBuilder txBuilder = new TransactionBuilder(notary);
|
||||
// DOCEND 19
|
||||
|
||||
// Otherwise, we can choose to instantiate it without one:
|
||||
@ -362,7 +357,7 @@ public class FlowCookbook {
|
||||
|
||||
// An output state can be added as a ``ContractState``, contract class name and notary.
|
||||
// DOCSTART 49
|
||||
txBuilder.addOutputState(ourOutputState, DummyContract.PROGRAM_ID, specificNotary);
|
||||
txBuilder.addOutputState(ourOutputState, DummyContract.PROGRAM_ID, notary);
|
||||
// DOCEND 49
|
||||
// We can also leave the notary field blank, in which case the transaction's default
|
||||
// notary is used.
|
||||
@ -372,7 +367,7 @@ public class FlowCookbook {
|
||||
// Or we can add the output state as a ``TransactionState``, which already specifies
|
||||
// the output's contract and notary.
|
||||
// DOCSTART 51
|
||||
TransactionState txState = new TransactionState(ourOutputState, DummyContract.PROGRAM_ID, specificNotary);
|
||||
TransactionState txState = new TransactionState(ourOutputState, DummyContract.PROGRAM_ID, notary);
|
||||
// DOCEND 51
|
||||
|
||||
// Commands can be added as ``Command``s.
|
||||
|
@ -97,7 +97,7 @@ class InitiatorFlow(val arg1: Boolean, val arg2: Int, private val counterparty:
|
||||
progressTracker.currentStep = ID_OTHER_NODES
|
||||
// DOCEND 18
|
||||
|
||||
// A transaction generally needs a notary:
|
||||
// Every transaction needs a notary:
|
||||
// - To prevent double-spends if the transaction has inputs
|
||||
// - To serve as a timestamping authority if the transaction has a
|
||||
// time-window
|
||||
@ -107,12 +107,7 @@ class InitiatorFlow(val arg1: Boolean, val arg2: Int, private val counterparty:
|
||||
organisation = "Notary Service",
|
||||
locality = "London",
|
||||
country = "GB")
|
||||
val specificNotary: Party = serviceHub.networkMapCache.getNotary(notaryName)!!
|
||||
// Alternatively, we can pick an arbitrary notary from the notary
|
||||
// list. However, it is always preferable to specify the notary
|
||||
// explicitly, as the notary list might change when new notaries are
|
||||
// introduced, or old ones decommissioned.
|
||||
val firstNotary: Party = serviceHub.networkMapCache.notaryIdentities.first()
|
||||
val notary: Party = serviceHub.networkMapCache.getNotary(notaryName)!!
|
||||
// DOCEND 01
|
||||
|
||||
// We may also need to identify a specific counterparty. We do so
|
||||
@ -328,7 +323,7 @@ class InitiatorFlow(val arg1: Boolean, val arg2: Int, private val counterparty:
|
||||
// If our transaction has input states or a time-window, we must instantiate it with a
|
||||
// notary.
|
||||
// DOCSTART 19
|
||||
val txBuilder: TransactionBuilder = TransactionBuilder(specificNotary)
|
||||
val txBuilder: TransactionBuilder = TransactionBuilder(notary)
|
||||
// DOCEND 19
|
||||
|
||||
// Otherwise, we can choose to instantiate it without one:
|
||||
@ -362,7 +357,7 @@ class InitiatorFlow(val arg1: Boolean, val arg2: Int, private val counterparty:
|
||||
|
||||
// An output state can be added as a ``ContractState``, contract class name and notary.
|
||||
// DOCSTART 49
|
||||
txBuilder.addOutputState(ourOutputState, DummyContract.PROGRAM_ID, specificNotary)
|
||||
txBuilder.addOutputState(ourOutputState, DummyContract.PROGRAM_ID, notary)
|
||||
// DOCEND 49
|
||||
// We can also leave the notary field blank, in which case the transaction's default
|
||||
// notary is used.
|
||||
@ -372,7 +367,7 @@ class InitiatorFlow(val arg1: Boolean, val arg2: Int, private val counterparty:
|
||||
// Or we can add the output state as a ``TransactionState``, which already specifies
|
||||
// the output's contract and notary.
|
||||
// DOCSTART 51
|
||||
val txState: TransactionState<DummyState> = TransactionState(ourOutputState, DummyContract.PROGRAM_ID, specificNotary)
|
||||
val txState: TransactionState<DummyState> = TransactionState(ourOutputState, DummyContract.PROGRAM_ID, notary)
|
||||
// DOCEND 51
|
||||
|
||||
// Commands can be added as ``Command``s.
|
||||
|
@ -1,10 +1,23 @@
|
||||
package net.corda.docs.kotlin
|
||||
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.contracts.Amount
|
||||
import net.corda.core.contracts.Issued
|
||||
import net.corda.core.contracts.StateAndContract
|
||||
import net.corda.core.contracts.StateAndRef
|
||||
import net.corda.core.contracts.withoutIssuer
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.TransactionSignature
|
||||
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.ReceiveStateAndRefFlow
|
||||
import net.corda.core.flows.ReceiveTransactionFlow
|
||||
import net.corda.core.flows.SendStateAndRefFlow
|
||||
import net.corda.core.flows.SendTransactionFlow
|
||||
import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.node.ServiceHub
|
||||
@ -24,7 +37,7 @@ private data class FxRequest(val tradeId: String,
|
||||
val amount: Amount<Issued<Currency>>,
|
||||
val owner: Party,
|
||||
val counterparty: Party,
|
||||
val notary: Party? = null)
|
||||
val notary: Party)
|
||||
|
||||
// DOCSTART 1
|
||||
// This is equivalent to the Cash.generateSpend
|
||||
@ -38,8 +51,7 @@ private fun gatherOurInputs(serviceHub: ServiceHub,
|
||||
val ourParties = ourKeys.map { serviceHub.identityService.partyFromKey(it) ?: throw IllegalStateException("Unable to resolve party from key") }
|
||||
val fungibleCriteria = QueryCriteria.FungibleAssetQueryCriteria(owner = ourParties)
|
||||
|
||||
val notaries = notary ?: serviceHub.networkMapCache.notaryIdentities.first()
|
||||
val vaultCriteria: QueryCriteria = QueryCriteria.VaultQueryCriteria(notary = listOf(notaries as AbstractParty))
|
||||
val vaultCriteria: QueryCriteria = QueryCriteria.VaultQueryCriteria(notary = listOf(notary as AbstractParty))
|
||||
|
||||
val logicalExpression = builder { CashSchemaV1.PersistentCashState::currency.equal(amountRequired.token.product.currencyCode) }
|
||||
val cashCriteria = QueryCriteria.VaultCustomQueryCriteria(logicalExpression)
|
||||
@ -90,19 +102,20 @@ class ForeignExchangeFlow(private val tradeId: String,
|
||||
private val baseCurrencyAmount: Amount<Issued<Currency>>,
|
||||
private val quoteCurrencyAmount: Amount<Issued<Currency>>,
|
||||
private val counterparty: Party,
|
||||
private val weAreBaseCurrencySeller: Boolean) : FlowLogic<SecureHash>() {
|
||||
private val weAreBaseCurrencySeller: Boolean,
|
||||
private val notary: Party) : FlowLogic<SecureHash>() {
|
||||
@Suspendable
|
||||
override fun call(): SecureHash {
|
||||
// Select correct sides of the Fx exchange to query for.
|
||||
// Specifically we own the assets we wish to sell.
|
||||
// Also prepare the other side query
|
||||
val (localRequest, remoteRequest) = if (weAreBaseCurrencySeller) {
|
||||
val local = FxRequest(tradeId, baseCurrencyAmount, ourIdentity, counterparty)
|
||||
val remote = FxRequest(tradeId, quoteCurrencyAmount, counterparty, ourIdentity)
|
||||
val local = FxRequest(tradeId, baseCurrencyAmount, ourIdentity, counterparty, notary)
|
||||
val remote = FxRequest(tradeId, quoteCurrencyAmount, counterparty, ourIdentity, notary)
|
||||
Pair(local, remote)
|
||||
} else {
|
||||
val local = FxRequest(tradeId, quoteCurrencyAmount, ourIdentity, counterparty)
|
||||
val remote = FxRequest(tradeId, baseCurrencyAmount, counterparty, ourIdentity)
|
||||
val local = FxRequest(tradeId, quoteCurrencyAmount, ourIdentity, counterparty, notary)
|
||||
val remote = FxRequest(tradeId, baseCurrencyAmount, counterparty, ourIdentity, notary)
|
||||
Pair(local, remote)
|
||||
}
|
||||
|
||||
|
@ -3,9 +3,24 @@
|
||||
package net.corda.docs.kotlin.txbuild
|
||||
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.contracts.Command
|
||||
import net.corda.core.contracts.CommandData
|
||||
import net.corda.core.contracts.Contract
|
||||
import net.corda.core.contracts.LinearState
|
||||
import net.corda.core.contracts.StateAndContract
|
||||
import net.corda.core.contracts.StateAndRef
|
||||
import net.corda.core.contracts.StateRef
|
||||
import net.corda.core.contracts.TypeOnlyCommandData
|
||||
import net.corda.core.contracts.UniqueIdentifier
|
||||
import net.corda.core.contracts.requireSingleCommand
|
||||
import net.corda.core.contracts.requireThat
|
||||
import net.corda.core.crypto.TransactionSignature
|
||||
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.identity.AbstractParty
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.node.services.queryBy
|
||||
@ -95,13 +110,12 @@ data class TradeApprovalContract(val blank: Unit? = null) : Contract {
|
||||
*/
|
||||
@InitiatingFlow
|
||||
class SubmitTradeApprovalFlow(private val tradeId: String,
|
||||
private val counterparty: Party) : FlowLogic<StateAndRef<TradeApprovalContract.State>>() {
|
||||
private val counterparty: Party,
|
||||
private val notary: Party) : FlowLogic<StateAndRef<TradeApprovalContract.State>>() {
|
||||
@Suspendable
|
||||
override fun call(): StateAndRef<TradeApprovalContract.State> {
|
||||
// Manufacture an initial state
|
||||
val tradeProposal = TradeApprovalContract.State(tradeId, ourIdentity, counterparty)
|
||||
// identify a notary. This might also be done external to the flow
|
||||
val notary = serviceHub.networkMapCache.notaryIdentities.first()
|
||||
// Create the TransactionBuilder and populate with the new state.
|
||||
val tx = TransactionBuilder(notary).withItems(
|
||||
StateAndContract(tradeProposal, TRADE_APPROVAL_PROGRAM_ID),
|
||||
|
@ -58,7 +58,8 @@ class FxTransactionBuildTutorialTest {
|
||||
POUNDS(100).issuedBy(nodeB.info.singleIdentity().ref(0x01)),
|
||||
DOLLARS(200).issuedBy(nodeA.info.singleIdentity().ref(0x01)),
|
||||
nodeB.info.singleIdentity(),
|
||||
weAreBaseCurrencySeller = false)).getOrThrow()
|
||||
weAreBaseCurrencySeller = false,
|
||||
notary = mockNet.defaultNotaryIdentity)).getOrThrow()
|
||||
// wait for the flow to finish and the vault updates to be done
|
||||
// Get the balances when the vault updates
|
||||
nodeAVaultUpdate.get()
|
||||
|
@ -17,7 +17,6 @@ import net.corda.finance.contracts.ICommercialPaperState
|
||||
import net.corda.finance.contracts.asset.CASH
|
||||
import net.corda.finance.contracts.asset.Cash
|
||||
import net.corda.testing.core.*
|
||||
import net.corda.testing.internal.rigorousMock
|
||||
import net.corda.testing.node.MockServices
|
||||
import net.corda.testing.node.ledger
|
||||
import net.corda.testing.node.transaction
|
||||
@ -77,7 +76,7 @@ class TutorialTestDSL {
|
||||
|
||||
// DOCSTART 2
|
||||
// This example test will fail with this exception.
|
||||
@Test(expected = IllegalStateException::class)
|
||||
@Test(expected = IllegalStateException::class, timeout=300_000)
|
||||
fun simpleCP() {
|
||||
val inState = getPaper()
|
||||
ledgerServices.ledger(dummyNotary.party) {
|
||||
@ -92,7 +91,7 @@ class TutorialTestDSL {
|
||||
|
||||
// DOCSTART 3
|
||||
// This example test will fail with this exception.
|
||||
@Test(expected = TransactionVerificationException.ContractRejection::class)
|
||||
@Test(expected = TransactionVerificationException.ContractRejection::class, timeout=300_000)
|
||||
fun simpleCPMove() {
|
||||
val inState = getPaper()
|
||||
ledgerServices.ledger(dummyNotary.party) {
|
||||
|
@ -51,7 +51,7 @@ class WorkflowTransactionBuildTutorialTest {
|
||||
// Setup a vault subscriber to wait for successful upload of the proposal to NodeB
|
||||
val nodeBVaultUpdate = bobNode.services.vaultService.updates.toFuture()
|
||||
// Kick of the proposal flow
|
||||
val flow1 = aliceNode.startFlow(SubmitTradeApprovalFlow("1234", bob))
|
||||
val flow1 = aliceNode.startFlow(SubmitTradeApprovalFlow("1234", bob, mockNet.defaultNotaryIdentity))
|
||||
// Wait for the flow to finish
|
||||
val proposalRef = flow1.getOrThrow()
|
||||
val proposalLinearId = proposalRef.state.data.linearId
|
||||
|
80
docs/source/features-versions.rst
Normal file
80
docs/source/features-versions.rst
Normal file
@ -0,0 +1,80 @@
|
||||
Corda Features to Versions
|
||||
==========================
|
||||
|
||||
New versions of Corda introduce new features. These fall into one of three categories which have subtle but important implications for
|
||||
node owners, application developers and network operators.
|
||||
|
||||
The first set are changes that have no impact on application developers or the Corda network protocol. An example would be support for
|
||||
a new HSM or database system, for example, and which are of interest only to a node's operator.
|
||||
|
||||
The second set are new or changed APIs, which are of interest to CorDapp developers. When a release of Corda ships such features, the
|
||||
Platform Version of that node is incremented so that a CorDapp that relies on such a new or changed feature can detect this (eg to
|
||||
prevent it from running on a node without the feature or to trigger an alternative optimised codepath if the feature is present). The
|
||||
app developer should set the CorDapp's minimumPlatformVersion parameter to signal the minimum Platform Version against which the app
|
||||
can run or has been tested. If the application has also been tested against a greater platform version and can exploit it if present,
|
||||
the node can also set the targetPlatformVersion field.
|
||||
|
||||
The third set of changes are those which could affect the operation of a Corda network. Examples would include a change to the
|
||||
serialisation format or flow/wire protocol, or introduction of a new transaction component. These are changes to the core data model and
|
||||
these features have the property that it is not safe for any node or application to take advantage of until all nodes on the network
|
||||
are capable of understanding them. Such features are thus only enabled in a node if the network to which it is connected has published
|
||||
a minimumPlatformVersion in its network parameters that is greater than or equal to the Corda Platform Version that introduced the
|
||||
feature. For example, Corda 4.0 nodes, which implement Corda Platform Version 4, can only take advantage of the Corda Reference States
|
||||
feature when connected to a network with mPV 4.
|
||||
|
||||
If there is a Platform Version below which your application will not run or is not supported, then signal that with the application's
|
||||
`CorDapp.mPV` field. This will prevent older nodes from running your app. Nodes which support newer Platform Versions may also use this
|
||||
field to trigger code paths that emulate behaviours that were in force on that older Platform Version to maximise compatibility. However,
|
||||
if you have tested your app against newer versions of Corda and know your node can take advantage of the new Platform Version behaviours
|
||||
if present, you can signal this by using `CorDapp.targetPV` to declare the latest Platform Version against which the app has been tested
|
||||
and is known to work. In this way, it is possible to ship CorDapps that can both run on all nodes supporting some minimum Platform Version
|
||||
of Corda as well as opt in to newer features should they happen to be available on any given node.
|
||||
|
||||
.. list-table:: Corda Features
|
||||
:header-rows: 1
|
||||
|
||||
* - Feature
|
||||
- Corda Platform Version (PV)
|
||||
- Min Network Platform Version (network mPV)
|
||||
- Introduced in OS version
|
||||
- Introduced in Enterprise version
|
||||
* - Observer Nodes
|
||||
- 2
|
||||
- 2
|
||||
- 2.0
|
||||
- n/a
|
||||
* - Corda Serialization Framework
|
||||
- 3
|
||||
- 3
|
||||
- 3.0
|
||||
- 3.0
|
||||
* - Hash Constraints
|
||||
- 1
|
||||
- 1
|
||||
- 1.0
|
||||
- 1.0
|
||||
* - Whitelist Constraints
|
||||
- 3
|
||||
- 3
|
||||
- 3.0
|
||||
- 3.0
|
||||
* - Inline Finality Flow
|
||||
- 4
|
||||
- 3
|
||||
- 4.0
|
||||
- 4.0
|
||||
* - Reference States
|
||||
- 4
|
||||
- 4
|
||||
- 4.0
|
||||
- 4.0
|
||||
* - Signature Constraints
|
||||
- 4
|
||||
- 4
|
||||
- 4.0
|
||||
- 4.0
|
||||
* - Underlying Support for Accounts
|
||||
- 5
|
||||
- 4
|
||||
- 4.3
|
||||
- 4.3
|
@ -12,7 +12,7 @@ A node can be created manually by creating a folder that contains the following
|
||||
|
||||
* A folder entitled ``cordapps`` containing any CorDapp JARs you want the node to load
|
||||
|
||||
* An up-to-date version of the ``network-parameters`` file ([see docs:](https://docs.corda.net/network-map.html#network-parameters)) generated by the bootstrapper tool
|
||||
* An up-to-date version of the ``network-parameters`` file (:ref:`see docs <network-parameters>`) generated by the bootstrapper tool
|
||||
|
||||
* **Optional:** A webserver JAR entitled ``corda-webserver-|corda_version|.jar`` that will connect to the node via RPC
|
||||
|
||||
|
@ -65,4 +65,4 @@ Corda guarantees that whenever one of these facts is shared by multiple nodes on
|
||||
|
||||
**Note:** Not all on-ledger facts are shared between peers. For example, Alice's fact 11 is not shared with Bob. Fact 11 could, in fact, not be shared with any other node at all. If this is the case, it is deemed a unilateral fact.
|
||||
|
||||
**Note:** Although there is no central ledger, it is possible to broadcast a basic fact to all participants should you wish to. You would do this by using the network map service to loop over all parties.De
|
||||
**Note:** Although there is no central ledger, it is possible to broadcast a basic fact to all participants should you wish to. You would do this by using the network map service to loop over all parties.
|
||||
|
@ -16,7 +16,7 @@ Unlike the official image, a `node.conf` file and CorDapps are embedded into the
|
||||
More backends may be added in future. The tool is open source, so contributions to add more
|
||||
destinations for the containers are welcome!
|
||||
|
||||
`Download the Corda Network Builder <https://software.r3.com/artifactory/corda-releases/net/corda/corda-tools-network-builder/|corda_version|/corda-tools-network-builder-|corda_version|.jar>`_.
|
||||
`Download the Corda Network Builder <https://software.r3.com/artifactory/corda-releases/net/corda/corda-tools-network-builder/|corda_version|/corda-tools-network-builder-|corda_version|-all.jar>`_.
|
||||
|
||||
.. _pre-requisites:
|
||||
|
||||
|
@ -77,6 +77,8 @@ cluster generated like this can be sized for the maximum size you may need, and
|
||||
|
||||
More information can be found in :doc:`network-bootstrapper`.
|
||||
|
||||
.. _network-parameters:
|
||||
|
||||
Network parameters
|
||||
------------------
|
||||
|
||||
@ -132,6 +134,8 @@ The current set of network parameters:
|
||||
Encountering an owned contract in a JAR that is not signed by the rightful owner is most likely a sign of malicious behaviour, and should be reported.
|
||||
The transaction verification logic will throw an exception when this happens.
|
||||
|
||||
.. note:: To determine which `minimumPlatformVersion` a zone must mandate in order to permit all the features of Corda |corda_version| see :doc:`features-versions`
|
||||
|
||||
More parameters will be added in future releases to regulate things like allowed port numbers, whether or not IPv6
|
||||
connectivity is required for zone members, required cryptographic algorithms and roll-out schedules (e.g. for moving to post quantum cryptography), parameters related to SGX and so on.
|
||||
|
||||
|
@ -27,9 +27,11 @@ The name must also obey the following constraints:
|
||||
|
||||
* The ``organisation``, ``locality`` and ``country`` attributes are present
|
||||
|
||||
* The ``state``, ``organisational-unit`` and ``common name`` attributes are optional
|
||||
* The ``state``, ``organisational-unit`` and ``common name`` attributes are optional
|
||||
|
||||
* The fields of the name have the following maximum character lengths:
|
||||
* The maximum number of characters in the whole x500 name string is 128 characters
|
||||
|
||||
* The fields of the name have character lengths **less** than the following maximum values:
|
||||
|
||||
* Common name: 64
|
||||
* Organisation: 128
|
||||
@ -40,12 +42,18 @@ The name must also obey the following constraints:
|
||||
* The ``country`` attribute is a valid `ISO 3166-1<https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2>` two letter code in upper-case
|
||||
|
||||
* The ``organisation`` field of the name obeys the following constraints:
|
||||
|
||||
* Has at least two letters
|
||||
* Does not include the following characters: ``,`` , ``"``, ``\``
|
||||
|
||||
* All data fields adhere to the following constraints:
|
||||
|
||||
* Upper-case first letter
|
||||
* Does not include the following characters: ``,``, ``=``, ``$``, ``"``, ``'``, ``\``
|
||||
* Is in NFKC normalization form
|
||||
* Does not contain the null character
|
||||
* Only the latin, common and inherited unicode scripts are supported
|
||||
* No double-spacing
|
||||
* No leading or trailing whitespace
|
||||
|
||||
This is to avoid right-to-left issues, debugging issues when we can't pronounce names over the phone, and
|
||||
character confusability attacks.
|
||||
|
@ -4,7 +4,102 @@ Release notes
|
||||
.. contents::
|
||||
:depth: 2
|
||||
|
||||
Welcome to the Corda 4.3 release notes. Please read these carefully to understand what’s new in this release and how the features can help you. Just as prior releases have brought with them commitments to wire and API stability, Corda 4.3 comes with those same guarantees. States and apps valid in Corda 3.0 are transparently usable in Corda 4.3.
|
||||
Welcome to the Corda 4.4 release notes. Please read these carefully to understand what’s new in this release and how the features can help you. Just as prior releases have brought with them commitments to wire and API stability, Corda 4.4 comes with those same guarantees. States and apps valid in Corda 3.0 are usable in Corda 4.4.
|
||||
|
||||
.. _release_notes_v4_4:
|
||||
|
||||
Corda 4.4
|
||||
=========
|
||||
|
||||
Corda 4.4 lays the foundation of a new open-core approach for the Corda codebase. This involved a refactoring of the main functional components of Corda. Please consult :doc:`cordapp-overview.rst` to get an overview of the practical impact on CorDapp development.
|
||||
|
||||
Furthermore, Corda 4.4 introduces improvements to the flow framework API, a new diagnostic ``ServiceHub`` call and includes a number of security enhancements.
|
||||
|
||||
Changes for developers in Corda 4.4
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Flows API improvements
|
||||
+++++++++++++++++++++++
|
||||
|
||||
Corda 4.4 introduces a new ``FlowLogic.await`` API that allows a CorDapp developer to suspend their flow when executing user-defined long-running operations (e.g. call-outs to external services). This prevents these long-running operations from blocking the flow thread, allowing other flows to progress in the interim. Previously, these operations had to be executed synchronously, blocking the flow thread.
|
||||
|
||||
The CorDapp developer can decide whether to run these asynchronous flow operations in a dedicated thread pool, or to handle the threading themselves directly.
|
||||
|
||||
Note that as before, the flow framework suspends automatically for certain operations (e.g. when waiting to receive a message from a counterparty). These suspensions do not have to be triggered explicitly.
|
||||
|
||||
The node operator can configure the number of threads in the threadpool to dedicate to external operations.
|
||||
|
||||
Corda 4.4 also introduces a new ``HospitalizeFlowException`` exception type that, when thrown, causes a flow to halt execution and send itself to the flow hospital for observation. The flow will automatically be retried on the next node start.
|
||||
|
||||
This exception gives user code a way to retry a flow from its last checkpoint if a known intermittent failure occurred.
|
||||
|
||||
|
||||
New utility APIs
|
||||
+++++++++++++++++++++++
|
||||
|
||||
Corda 4.4 introduces a new call (``ServiceHub.DiagnosticsService``) available to CorDapp developers that allows them to access:
|
||||
|
||||
* The edition of Corda being run (e.g. Open Source, Enterprise)
|
||||
* The version of Corda being run including the patch number (eg. 3.2.20190215)
|
||||
|
||||
Corda 4.4 also provides a callback (``AppServiceHub.register``) to allow Corda services to register custom actions to be performed once the node is fully started-up. This pattern prevents issues caused by the service trying to immediately access a part of the node that hadn't yet been initialised .
|
||||
|
||||
Security enhancements
|
||||
+++++++++++++++++++++++
|
||||
|
||||
* The SSH server in the :doc:`shell` has been updated to remove outdated weak ciphers and algorithms.
|
||||
* The ability to SSH into the standalone shell has been removed
|
||||
* A new read-only RPC user role template has been documented in :doc:`shell`
|
||||
|
||||
|
||||
Platform version change
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Given the addition of new APIs, the platform version of Corda 4.4 has been bumped up from 5 to 6. This is to prevent CorDapps that use it being deployed onto nodes unable to host them. Note that the minimum platform version has not been changed - this means that older Corda nodes can still interoperate with Corda 4.4 nodes. Since the APIs added do not affect the wire protocol or have other zone-level implications, applications can take advantage of these new platform version 6 features even if the Corda 4.4 node is running on a network whose minimum platform version is 4.
|
||||
|
||||
For more information on platform version, please see :doc:`versioning`. For more details on upgrading a CorDapp to use platform version 5, please see :doc:`app-upgrade-notes`.
|
||||
|
||||
|
||||
Issues Fixed
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* A failure response from Doorman during initial registration causes a class cast exception [`CORDA-2744 <https://r3-cev.atlassian.net/browse/CORDA-2744>`_]
|
||||
* Add an exception for Unrecoverable RPC errors [`CORDA-3192 <https://r3-cev.atlassian.net/browse/CORDA-3192>`_]
|
||||
* Fix the misleading Flow has been waiting message [`CORDA-3197 <https://r3-cev.atlassian.net/browse/CORDA-3197>`_]
|
||||
* Update Quasar agent so that we can exclude entire ClassLoaders from being instrumented [`CORDA-3228 <https://r3-cev.atlassian.net/browse/CORDA-3228>`_]
|
||||
* Don't fail on liquibase errors when using H2 [`CORDA-3302 <https://r3-cev.atlassian.net/browse/CORDA-3302>`_]
|
||||
* Exceptions thrown in raw vault observers can cause critical issues [`CORDA-3329 <https://r3-cev.atlassian.net/browse/CORDA-3329>`_]
|
||||
* Migration from Corda 3.x to 4.x for PostgreSQL require a manual workaround [`CORDA-3348 <https://r3-cev.atlassian.net/browse/CORDA-3348>`_]
|
||||
* Prepare DJVM library for 1.0 release [`CORDA-3377 <https://r3-cev.atlassian.net/browse/CORDA-3377>`_]
|
||||
* Improve node configuration override documentation [`CORDA-3386 <https://r3-cev.atlassian.net/browse/CORDA-3386>`_]
|
||||
* Allow EvolutionSerializer to handle primitive types becoming nullable [`CORDA-3390 <https://r3-cev.atlassian.net/browse/CORDA-3390>`_]
|
||||
* Fix caching of local AMQPSerializer [`CORDA-3392 <https://r3-cev.atlassian.net/browse/CORDA-3392>`_]
|
||||
* Fixed NPE in BlobInspector [`CORDA-3396 <https://r3-cev.atlassian.net/browse/CORDA-3396>`_]
|
||||
* Update DemoBench so that using the DJVM is configurable [`CORDA-3406 <https://r3-cev.atlassian.net/browse/CORDA-3406>`_]
|
||||
* Scanning for Custom Serializers in the context of transaction verification is broken [`CORDA-3464 <https://r3-cev.atlassian.net/browse/CORDA-3464>`_]
|
||||
* Allow EvolutionSerializer to handle boxed types becoming primitive [`CORDA-3469 <https://r3-cev.atlassian.net/browse/CORDA-3469>`_]
|
||||
* Create interface to perform transactional operations from custom CordaServices [`CORDA-3471 <https://r3-cev.atlassian.net/browse/CORDA-3471>`_]
|
||||
* Fix typo in node database table documentation [`CORDA-3476 <https://r3-cev.atlassian.net/browse/CORDA-3476>`_]
|
||||
* Fix node database page [`CORDA-3477 <https://r3-cev.atlassian.net/browse/CORDA-3477>`_]
|
||||
* Add timestamp column to NODE_TRANSACTIONS table [`CORDA-3479 <https://r3-cev.atlassian.net/browse/CORDA-3479>`_]
|
||||
* Support adding new mandatory field and removal of optional [`CORDA-3489 <https://r3-cev.atlassian.net/browse/CORDA-3489>`_]
|
||||
* Fix link to network builder [`CORDA-3495 <https://r3-cev.atlassian.net/browse/CORDA-3495>`_]
|
||||
* Provide option for user to specify custom serializers without classpath scanning [`CORDA-3501 <https://r3-cev.atlassian.net/browse/CORDA-3501>`_]
|
||||
* The CordaRPCClientConfiguration is not respected when GracefulReconnect is used [`CORDA-3507 <https://r3-cev.atlassian.net/browse/CORDA-3507>`_]
|
||||
* Fix for Could not start flow as connection failed error on starting flow via ShellCli if user is not authorized to use this flow [`CORDA-3513 <https://r3-cev.atlassian.net/browse/CORDA-3513>`_]
|
||||
* Support whitelists and custom serializers inside the DJVM [`CORDA-3523 <https://r3-cev.atlassian.net/browse/CORDA-3523>`_]
|
||||
* Load DJVM serialization types more precisely to avoid runtime warnings [`CORDA-3536 <https://r3-cev.atlassian.net/browse/CORDA-3536>`_]
|
||||
* Use the config values for reconnecting retry interval and max reconnect attempts [`CORDA-3542 <https://r3-cev.atlassian.net/browse/CORDA-3542>`_]
|
||||
* SSH memory leak and security [`CORDA-3520 <https://r3-cev.atlassian.net/browse/CORDA-3520>`_]
|
||||
* Remove support for outdated ciphers and algorithms from SSH [`CORDA-3550 <https://r3-cev.atlassian.net/browse/CORDA-3550>`_]
|
||||
* Deserialization using the DJVM creates too many SerializerFactory objects [`CORDA-3552 <https://r3-cev.atlassian.net/browse/CORDA-3552>`_]
|
||||
* Allow initial registration errors to propagate up so the node exits with a failure code [`CORDA-3558 <https://r3-cev.atlassian.net/browse/CORDA-3558>`_]
|
||||
* Remove reference to man run [`CORDA-3559 <https://r3-cev.atlassian.net/browse/CORDA-3559>`_]
|
||||
* Always add TestCordapps to the classpath when building _driverSerializationEnv [`CORDA-3566 <https://r3-cev.atlassian.net/browse/CORDA-3566>`_]
|
||||
* Use the connectionMaxRetryInterval configuration when reconnection the RPC client [`CORDA-3576 <https://r3-cev.atlassian.net/browse/CORDA-3576>`_]
|
||||
* Update docs for X500 name and SSH hostkey [`CORDA-3585 <https://r3-cev.atlassian.net/browse/CORDA-3585>`_]
|
||||
* hashLookup command help misspelling [`CORDA-3587 <https://r3-cev.atlassian.net/browse/CORDA-3587>`_]
|
||||
* Exit the InteractiveShell on shutdown command [`CORDA-3593 <https://r3-cev.atlassian.net/browse/CORDA-3593>`_]
|
||||
|
||||
.. _release_notes_v4_3:
|
||||
|
||||
@ -446,7 +541,7 @@ Corda 4
|
||||
Welcome to the Corda 4 release notes. Please read these carefully to understand what's new in this
|
||||
release and how the changes can help you. Just as prior releases have brought with them commitments
|
||||
to wire and API stability, Corda 4 comes with those same guarantees. States and apps valid in
|
||||
Corda 3 are transparently usable in Corda 4.
|
||||
Corda 3 are usable in Corda 4.
|
||||
|
||||
For app developers, we strongly recommend reading ":doc:`app-upgrade-notes`". This covers the upgrade
|
||||
procedure, along with how you can adjust your app to opt-in to new features making your app more secure and
|
||||
|
@ -91,6 +91,8 @@ The host key is loaded from the ``<node root directory>/sshkey/hostkey.pem`` fil
|
||||
generated automatically. In development mode, the seed may be specified to give the same results on the same computer
|
||||
in order to avoid host-checking errors.
|
||||
|
||||
Only RSA key is currently supported as a host key. If ``hostkey.pem`` is not RSA, it will be replaced by the newly generated RSA key.
|
||||
|
||||
Connecting to the shell
|
||||
***********************
|
||||
|
||||
|
@ -121,7 +121,7 @@ class Caplet {
|
||||
}
|
||||
}
|
||||
|
||||
@Test @Ignore
|
||||
@Test(timeout=300_000) @Ignore
|
||||
fun `pretty print`() {
|
||||
println ( prettyPrint(contract) )
|
||||
|
||||
|
@ -117,7 +117,7 @@ class Examples {
|
||||
}
|
||||
}
|
||||
|
||||
@Test @Ignore
|
||||
@Test(timeout=300_000) @Ignore
|
||||
fun `pretty print`() {
|
||||
println ( prettyPrint(cds_contract) )
|
||||
|
||||
|
@ -125,7 +125,7 @@ class FXFwdTimeOption {
|
||||
}
|
||||
}
|
||||
|
||||
@Test @Ignore
|
||||
@Test(timeout=300_000) @Ignore
|
||||
fun `pretty print`() {
|
||||
println ( prettyPrint(initialContract) )
|
||||
|
||||
|
@ -164,7 +164,7 @@ class FXSwap {
|
||||
}
|
||||
}
|
||||
|
||||
@Test @Ignore
|
||||
@Test(timeout=300_000) @Ignore
|
||||
fun `pretty print`() {
|
||||
println ( prettyPrint(contract) )
|
||||
}
|
||||
|
@ -202,7 +202,7 @@ class IRS {
|
||||
}
|
||||
}
|
||||
|
||||
@Test @Ignore
|
||||
@Test(timeout=300_000) @Ignore
|
||||
fun `pretty print`() {
|
||||
println ( prettyPrint(contractInitial) )
|
||||
|
||||
|
@ -22,7 +22,7 @@ import net.corda.testing.core.*
|
||||
import net.corda.testing.dsl.EnforceVerifyOrFail
|
||||
import net.corda.testing.dsl.TransactionDSL
|
||||
import net.corda.testing.dsl.TransactionDSLInterpreter
|
||||
import net.corda.testing.internal.TEST_TX_TIME
|
||||
import net.corda.coretesting.internal.TEST_TX_TIME
|
||||
import net.corda.testing.internal.vault.VaultFiller
|
||||
import net.corda.testing.node.MockServices
|
||||
import net.corda.testing.node.MockServices.Companion.makeTestDatabaseAndMockServices
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user