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:
LankyDan 2020-03-12 08:56:59 +00:00
commit ac3f880ae4
333 changed files with 4795 additions and 1983 deletions

View File

@ -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)
##

View File

@ -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 {

View File

@ -1,4 +1,5 @@
integration: { allParallelIntegrationTest }
pr-merge: { parallelRegressionTest }
smoke: { allParallelSmokeTest }
slow: { allParallelSlowIntegrationTest }
unit: { allParallelUnitTest }

View File

@ -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
View File

@ -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"
}
}

View File

@ -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

View File

@ -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

View File

@ -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
)
}
}

View File

@ -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) {

View File

@ -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)

View File

@ -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

View File

@ -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()

View File

@ -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())) {

View File

@ -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

View File

@ -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?>>

View File

@ -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

View File

@ -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)
}
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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))
}
}
}

View File

@ -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 }

View File

@ -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"

View File

@ -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
}
}

View File

@ -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())
}
}

View File

@ -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!!

View File

@ -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

View File

@ -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">

View File

@ -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

View File

@ -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

View File

@ -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
}

View File

@ -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 {

View File

@ -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")

View File

@ -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'

View File

@ -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)

View File

@ -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

View File

@ -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()

View File

@ -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()

View File

@ -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))

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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()
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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 */

View File

@ -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."

View File

@ -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

View File

@ -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

View File

@ -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
}
}
}

View File

@ -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()
}
}

View File

@ -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))

View File

@ -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
}
}
}

View File

@ -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())

View File

@ -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)
}

View File

@ -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.")
}
}

View File

@ -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>

View 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"
}

View File

@ -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()
)
)
}

View File

@ -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)
}
}

View File

@ -0,0 +1 @@
net.corda.detekt.plugins.CordaDetektProvider

View File

@ -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)
}
}

View File

@ -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/*

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
~~~~~~~~~~~~

View File

@ -460,6 +460,7 @@ Please note that suspendable flow operations such as:
* ``FlowSession.send``
* ``FlowSession.receive``
* ``FlowLogic.receiveAll``
* ``FlowLogic.sendAll``
* ``FlowLogic.sleep``
* ``FlowLogic.subFlow``

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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)
}

View File

@ -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),

View File

@ -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()

View File

@ -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) {

View File

@ -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

View 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

View File

@ -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

View File

@ -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.

View File

@ -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:

View File

@ -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.

View File

@ -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.

View File

@ -4,7 +4,102 @@ Release notes
.. contents::
:depth: 2
Welcome to the Corda 4.3 release notes. Please read these carefully to understand whats 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 whats 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

View File

@ -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
***********************

View File

@ -121,7 +121,7 @@ class Caplet {
}
}
@Test @Ignore
@Test(timeout=300_000) @Ignore
fun `pretty print`() {
println ( prettyPrint(contract) )

View File

@ -117,7 +117,7 @@ class Examples {
}
}
@Test @Ignore
@Test(timeout=300_000) @Ignore
fun `pretty print`() {
println ( prettyPrint(cds_contract) )

View File

@ -125,7 +125,7 @@ class FXFwdTimeOption {
}
}
@Test @Ignore
@Test(timeout=300_000) @Ignore
fun `pretty print`() {
println ( prettyPrint(initialContract) )

View File

@ -164,7 +164,7 @@ class FXSwap {
}
}
@Test @Ignore
@Test(timeout=300_000) @Ignore
fun `pretty print`() {
println ( prettyPrint(contract) )
}

View File

@ -202,7 +202,7 @@ class IRS {
}
}
@Test @Ignore
@Test(timeout=300_000) @Ignore
fun `pretty print`() {
println ( prettyPrint(contractInitial) )

View File

@ -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