diff --git a/core-tests/src/smoke-test/kotlin/net/corda/coretests/verification/ExternalVerificationTests.kt b/core-tests/src/smoke-test/kotlin/net/corda/coretests/verification/ExternalVerificationTests.kt index df98af5b3f..9a662a7888 100644 --- a/core-tests/src/smoke-test/kotlin/net/corda/coretests/verification/ExternalVerificationTests.kt +++ b/core-tests/src/smoke-test/kotlin/net/corda/coretests/verification/ExternalVerificationTests.kt @@ -26,6 +26,7 @@ import net.corda.finance.flows.CashIssueFlow import net.corda.finance.flows.CashPaymentFlow import net.corda.finance.workflows.getCashBalance import net.corda.legacy.workflows.LegacyIssuanceFlow +import net.corda.legacy.workflows.LegacyIssuanceWithSystemEnvVarFlow import net.corda.nodeapi.internal.config.User import net.corda.smoketesting.NodeParams import net.corda.smoketesting.NodeProcess @@ -139,12 +140,24 @@ class ExternalVerificationSignedCordappsTest { currentNode.assertTransactionsWereVerified(BOTH, issuanceStateRef.txhash) } + @Test(timeout = 300_000) + fun `validate external verifier started with system environment variable defined`() { + val issuanceStateRef = checkSystemEnvVarDefined(currentNode) + currentNode.assertTransactionsWereVerified(BOTH, issuanceStateRef.txhash) + } + private fun legacyJackonIssuance(issuer: NodeProcess): StateRef { val issuerRpc = issuer.connect(superUser).proxy val issuanceStateRef = issuerRpc.startFlowDynamic(LegacyIssuanceFlow::class.java, 2).returnValue.getOrThrow() as StateRef return issuanceStateRef } + private fun checkSystemEnvVarDefined(issuer: NodeProcess): StateRef { + val issuerRpc = issuer.connect(superUser).proxy + val issuanceStateRef = issuerRpc.startFlowDynamic(LegacyIssuanceWithSystemEnvVarFlow::class.java, 2).returnValue.getOrThrow() as StateRef + return issuanceStateRef + } + private fun cashIssuanceAndPayment(issuer: NodeProcess, recipient: NodeProcess): Pair { val issuerRpc = issuer.connect(superUser).proxy val recipientRpc = recipient.connect(superUser).proxy diff --git a/legacy411/src/main/java/net/corda/legacy/contracts/AnotherDummyContractWithSystemEnvVarDefined.java b/legacy411/src/main/java/net/corda/legacy/contracts/AnotherDummyContractWithSystemEnvVarDefined.java new file mode 100644 index 0000000000..fd84271201 --- /dev/null +++ b/legacy411/src/main/java/net/corda/legacy/contracts/AnotherDummyContractWithSystemEnvVarDefined.java @@ -0,0 +1,119 @@ +package net.corda.legacy.contracts; + +import kotlin.collections.CollectionsKt; +import kotlin.jvm.internal.Intrinsics; +import net.corda.core.contracts.Command; +import net.corda.core.contracts.CommandData; +import net.corda.core.contracts.Contract; +import net.corda.core.contracts.ContractState; +import net.corda.core.contracts.PartyAndReference; +import net.corda.core.contracts.StateAndContract; +import net.corda.core.contracts.TypeOnlyCommandData; +import net.corda.core.identity.AbstractParty; +import net.corda.core.identity.Party; +import net.corda.core.transactions.LedgerTransaction; +import net.corda.core.transactions.TransactionBuilder; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public final class AnotherDummyContractWithSystemEnvVarDefined implements Contract { + @NotNull + private final String magicString = "helloworld"; + @NotNull + public static final String ANOTHER_DUMMY_PROGRAM_ID = "net.corda.legacy.contracts.AnotherDummyContractWithSystemEnvVarDefined"; + + @NotNull + public final String getMagicString() { + return this.magicString; + } + + public void verify(@NotNull LedgerTransaction tx) { + + Intrinsics.checkNotNullParameter(tx, "tx"); + String userName = System.getProperty("user.name"); + if (userName == null || !userName.equals("Alice")) { + throw new IllegalStateException("System property 'user.name' not valid, wanted 'Alice' but got " + userName); + } + String birdSize = System.getProperty("bird.size"); + if (birdSize == null || !birdSize.equals("big")) { + throw new IllegalStateException("System property 'bird.size' not valid, wanted 'big' but got " + birdSize); + } + } + + @NotNull + public final TransactionBuilder generateInitial(@NotNull PartyAndReference owner, int magicNumber, @NotNull Party notary) { + Intrinsics.checkNotNullParameter(owner, "owner"); + Intrinsics.checkNotNullParameter(notary, "notary"); + State state = new State(magicNumber); + TransactionBuilder var10000 = new TransactionBuilder(notary); + Object[] var5 = new Object[]{new StateAndContract((ContractState) state, ANOTHER_DUMMY_PROGRAM_ID), new Command(new Commands.Create(), owner.getParty().getOwningKey())}; + return var10000.withItems(var5); + } + + public final int inspectState(@NotNull ContractState state) { + Intrinsics.checkNotNullParameter(state, "state"); + return ((State) state).getMagicNumber(); + } + + public interface Commands extends CommandData { + public static final class Create extends TypeOnlyCommandData implements Commands { + } + } + + public static final class State implements ContractState { + private final int magicNumber; + + public State(int magicNumber) { + this.magicNumber = magicNumber; + } + + public final int getMagicNumber() { + return this.magicNumber; + } + + @NotNull + public List getParticipants() { + return CollectionsKt.emptyList(); + } + + public final int component1() { + return this.magicNumber; + } + + @NotNull + public final State copy(int magicNumber) { + return new State(magicNumber); + } + + // $FF: synthetic method + public static State copy$default(State var0, int var1, int var2, Object var3) { + if ((var2 & 1) != 0) { + var1 = var0.magicNumber; + } + + return var0.copy(var1); + } + + @NotNull + public String toString() { + return "State(magicNumber=" + this.magicNumber + ')'; + } + + public int hashCode() { + return Integer.hashCode(this.magicNumber); + } + + public boolean equals(@Nullable Object other) { + if (this == other) { + return true; + } else if (!(other instanceof State)) { + return false; + } else { + State var2 = (State) other; + return this.magicNumber == var2.magicNumber; + } + } + } +} diff --git a/legacy412/src/main/java/net/corda/legacy/contracts/AnotherDummyContractWithSystemEnvVarDefined.java b/legacy412/src/main/java/net/corda/legacy/contracts/AnotherDummyContractWithSystemEnvVarDefined.java new file mode 100644 index 0000000000..fd84271201 --- /dev/null +++ b/legacy412/src/main/java/net/corda/legacy/contracts/AnotherDummyContractWithSystemEnvVarDefined.java @@ -0,0 +1,119 @@ +package net.corda.legacy.contracts; + +import kotlin.collections.CollectionsKt; +import kotlin.jvm.internal.Intrinsics; +import net.corda.core.contracts.Command; +import net.corda.core.contracts.CommandData; +import net.corda.core.contracts.Contract; +import net.corda.core.contracts.ContractState; +import net.corda.core.contracts.PartyAndReference; +import net.corda.core.contracts.StateAndContract; +import net.corda.core.contracts.TypeOnlyCommandData; +import net.corda.core.identity.AbstractParty; +import net.corda.core.identity.Party; +import net.corda.core.transactions.LedgerTransaction; +import net.corda.core.transactions.TransactionBuilder; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public final class AnotherDummyContractWithSystemEnvVarDefined implements Contract { + @NotNull + private final String magicString = "helloworld"; + @NotNull + public static final String ANOTHER_DUMMY_PROGRAM_ID = "net.corda.legacy.contracts.AnotherDummyContractWithSystemEnvVarDefined"; + + @NotNull + public final String getMagicString() { + return this.magicString; + } + + public void verify(@NotNull LedgerTransaction tx) { + + Intrinsics.checkNotNullParameter(tx, "tx"); + String userName = System.getProperty("user.name"); + if (userName == null || !userName.equals("Alice")) { + throw new IllegalStateException("System property 'user.name' not valid, wanted 'Alice' but got " + userName); + } + String birdSize = System.getProperty("bird.size"); + if (birdSize == null || !birdSize.equals("big")) { + throw new IllegalStateException("System property 'bird.size' not valid, wanted 'big' but got " + birdSize); + } + } + + @NotNull + public final TransactionBuilder generateInitial(@NotNull PartyAndReference owner, int magicNumber, @NotNull Party notary) { + Intrinsics.checkNotNullParameter(owner, "owner"); + Intrinsics.checkNotNullParameter(notary, "notary"); + State state = new State(magicNumber); + TransactionBuilder var10000 = new TransactionBuilder(notary); + Object[] var5 = new Object[]{new StateAndContract((ContractState) state, ANOTHER_DUMMY_PROGRAM_ID), new Command(new Commands.Create(), owner.getParty().getOwningKey())}; + return var10000.withItems(var5); + } + + public final int inspectState(@NotNull ContractState state) { + Intrinsics.checkNotNullParameter(state, "state"); + return ((State) state).getMagicNumber(); + } + + public interface Commands extends CommandData { + public static final class Create extends TypeOnlyCommandData implements Commands { + } + } + + public static final class State implements ContractState { + private final int magicNumber; + + public State(int magicNumber) { + this.magicNumber = magicNumber; + } + + public final int getMagicNumber() { + return this.magicNumber; + } + + @NotNull + public List getParticipants() { + return CollectionsKt.emptyList(); + } + + public final int component1() { + return this.magicNumber; + } + + @NotNull + public final State copy(int magicNumber) { + return new State(magicNumber); + } + + // $FF: synthetic method + public static State copy$default(State var0, int var1, int var2, Object var3) { + if ((var2 & 1) != 0) { + var1 = var0.magicNumber; + } + + return var0.copy(var1); + } + + @NotNull + public String toString() { + return "State(magicNumber=" + this.magicNumber + ')'; + } + + public int hashCode() { + return Integer.hashCode(this.magicNumber); + } + + public boolean equals(@Nullable Object other) { + if (this == other) { + return true; + } else if (!(other instanceof State)) { + return false; + } else { + State var2 = (State) other; + return this.magicNumber == var2.magicNumber; + } + } + } +} diff --git a/legacy412/src/main/java/net/corda/legacy/workflows/LegacyIssuanceWithSystemEnvVarFlow.java b/legacy412/src/main/java/net/corda/legacy/workflows/LegacyIssuanceWithSystemEnvVarFlow.java new file mode 100644 index 0000000000..1b5b36724c --- /dev/null +++ b/legacy412/src/main/java/net/corda/legacy/workflows/LegacyIssuanceWithSystemEnvVarFlow.java @@ -0,0 +1,54 @@ +package net.corda.legacy.workflows; + +import co.paralleluniverse.fibers.Suspendable; +import kotlin.collections.CollectionsKt; +import kotlin.jvm.internal.Intrinsics; +import net.corda.core.contracts.AttachmentResolutionException; +import net.corda.core.contracts.StateRef; +import net.corda.core.contracts.TransactionResolutionException; +import net.corda.core.contracts.TransactionVerificationException; +import net.corda.core.flows.FlowLogic; +import net.corda.core.flows.StartableByRPC; +import net.corda.core.identity.Party; +import net.corda.core.node.ServiceHub; +import net.corda.core.transactions.SignedTransaction; +import net.corda.core.transactions.TransactionBuilder; +import net.corda.legacy.contracts.AnotherDummyContractWithSystemEnvVarDefined; +import org.jetbrains.annotations.NotNull; + +import java.security.SignatureException; + +@StartableByRPC +public final class LegacyIssuanceWithSystemEnvVarFlow extends FlowLogic { + private final int magicNumber; + + public LegacyIssuanceWithSystemEnvVarFlow(int magicNumber) { + this.magicNumber = magicNumber; + } + + @Suspendable + @NotNull + public StateRef call() { + ServiceHub var10000 = this.getServiceHub(); + AnotherDummyContractWithSystemEnvVarDefined var10001 = new AnotherDummyContractWithSystemEnvVarDefined(); + Party var10002 = this.getOurIdentity(); + byte[] var3 = new byte[]{0}; + TransactionBuilder var2 = var10001.generateInitial(var10002.ref(var3), this.magicNumber, (Party) CollectionsKt.first(this.getServiceHub().getNetworkMapCache().getNotaryIdentities())); + Intrinsics.checkNotNullExpressionValue(var2, "generateInitial(...)"); + SignedTransaction stx = var10000.signInitialTransaction(var2); + try { + stx.verify(this.getServiceHub(), false); + } catch (SignatureException e) { + throw new RuntimeException(e); + } catch (AttachmentResolutionException e) { + throw new RuntimeException(e); + } catch (TransactionResolutionException e) { + throw new RuntimeException(e); + } catch (TransactionVerificationException e) { + throw new RuntimeException(e); + } + //SignedTransaction.verify$default(stx, this.getServiceHub(), false, 2, (Object)null); + this.getServiceHub().recordTransactions(stx, new SignedTransaction[0]); + return stx.getTx().outRef(0).getRef(); + } +} diff --git a/testing/smoke-test-utils/src/main/kotlin/net/corda/smoketesting/NodeParams.kt b/testing/smoke-test-utils/src/main/kotlin/net/corda/smoketesting/NodeParams.kt index e33cd6dbc6..04951ab65a 100644 --- a/testing/smoke-test-utils/src/main/kotlin/net/corda/smoketesting/NodeParams.kt +++ b/testing/smoke-test-utils/src/main/kotlin/net/corda/smoketesting/NodeParams.kt @@ -43,7 +43,8 @@ class NodeParams @JvmOverloads constructor( .withValue("jarDirs", valueFor(jarDirs.map(Path::absolutePathString))) .withValue("devMode", valueFor(devMode)) .withValue("custom", empty() - .withValue("externalVerifierJvmArgs", valueFor(listOf("-Duser.name=Alice"))) + .withValue("externalVerifierJvmArgs", valueFor(listOf("-Duser.name=Alice", "-Dbird.size=big"))) + .withValue("jvmArgs", valueFor(listOf("-Duser.name=Alice", "-Dbird.size=big"))) .root()) return if (isNotary) { config.withValue("notary", ConfigValueFactory.fromMap(mapOf("validating" to true)))