ENT-12568: Added a test to check system property is defined in external verifier. (#7898)

This commit is contained in:
Adel El-Beik 2025-01-22 18:00:25 +00:00 committed by GitHub
parent 7b6df5cc14
commit 781aaba649
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 307 additions and 1 deletions

View File

@ -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<SignedTransaction, SignedTransaction> {
val issuerRpc = issuer.connect(superUser).proxy
val recipientRpc = recipient.connect(superUser).proxy

View File

@ -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<Commands.Create>(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<AbstractParty> 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;
}
}
}
}

View File

@ -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<Commands.Create>(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<AbstractParty> 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;
}
}
}
}

View File

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

View File

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