mirror of
https://github.com/corda/corda.git
synced 2024-12-18 12:46:29 +00:00
ENT-12248 Support for a new legacy-jars directory of 3rd party JARs for the external verifier
This commit is contained in:
parent
babaceab5d
commit
38d7d71a63
@ -54,7 +54,15 @@ processSmokeTestResources {
|
||||
rename 'corda-finance-contracts-.*.jar', 'corda-finance-contracts.jar'
|
||||
}
|
||||
from(tasks.getByPath(":testing:cordapps:4.11-workflows:jar"))
|
||||
from(configurations.corda4_11)
|
||||
from(configurations.corda4_11) {
|
||||
rename 'jackson-core-.*.jar', 'jackson-core.jar'
|
||||
}
|
||||
from(tasks.getByPath(":legacy411:jar")) {
|
||||
rename 'legacy411-.*.jar', 'legacy411.jar'
|
||||
}
|
||||
from(tasks.getByPath(":legacy412:jar")) {
|
||||
rename 'legacy412-.*.jar', 'legacy412.jar'
|
||||
}
|
||||
}
|
||||
|
||||
processIntegrationTestResources {
|
||||
@ -123,6 +131,8 @@ dependencies {
|
||||
smokeTestImplementation project(":finance:workflows")
|
||||
smokeTestImplementation project(":testing:cordapps:4.11-workflows")
|
||||
smokeTestImplementation project(":finance:contracts")
|
||||
smokeTestImplementation project(":legacy411")
|
||||
smokeTestImplementation project(":legacy412")
|
||||
smokeTestImplementation "org.assertj:assertj-core:${assertj_version}"
|
||||
smokeTestImplementation "org.bouncycastle:bcprov-lts8on:${bouncycastle_version}"
|
||||
smokeTestImplementation "co.paralleluniverse:quasar-core:$quasar_version"
|
||||
@ -137,6 +147,7 @@ dependencies {
|
||||
corda4_11 "net.corda:corda-finance-contracts:4.11"
|
||||
corda4_11 "net.corda:corda-finance-workflows:4.11"
|
||||
corda4_11 "net.corda:corda:4.11"
|
||||
corda4_11 "com.fasterxml.jackson.core:jackson-core:2.17.2"
|
||||
}
|
||||
|
||||
tasks.withType(Test).configureEach {
|
||||
|
@ -3,6 +3,7 @@ package net.corda.coretests.verification
|
||||
import net.corda.client.rpc.CordaRPCClientConfiguration
|
||||
import net.corda.client.rpc.notUsed
|
||||
import net.corda.core.contracts.Amount
|
||||
import net.corda.core.contracts.StateRef
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.flows.UnexpectedFlowEndException
|
||||
import net.corda.core.identity.CordaX500Name
|
||||
@ -24,6 +25,7 @@ import net.corda.finance.flows.AbstractCashFlow
|
||||
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.nodeapi.internal.config.User
|
||||
import net.corda.smoketesting.NodeParams
|
||||
import net.corda.smoketesting.NodeProcess
|
||||
@ -63,6 +65,8 @@ class ExternalVerificationSignedCordappsTest {
|
||||
val (legacyContractsCordapp, legacyWorkflowsCordapp) = listOf("contracts", "workflows").map { smokeTestResource("corda-finance-$it-4.11.jar") }
|
||||
// The current version finance CorDapp jars
|
||||
val currentCordapps = listOf("contracts", "workflows").map { smokeTestResource("corda-finance-$it.jar") }
|
||||
val legacyJacksonCordapp411 = smokeTestResource("legacy411.jar")
|
||||
val legacyJacksonCordapp412 = smokeTestResource("legacy412.jar")
|
||||
|
||||
notaries = factory.createNotaries(
|
||||
nodeParams(DUMMY_NOTARY_NAME, cordappJars = currentCordapps, legacyContractJars = listOf(legacyContractsCordapp)),
|
||||
@ -76,9 +80,15 @@ class ExternalVerificationSignedCordappsTest {
|
||||
))
|
||||
currentNode = factory.createNode(nodeParams(
|
||||
CordaX500Name("New", "York", "US"),
|
||||
currentCordapps,
|
||||
listOf(legacyContractsCordapp)
|
||||
currentCordapps + listOf(legacyJacksonCordapp412),
|
||||
listOf(legacyContractsCordapp, legacyJacksonCordapp411)
|
||||
))
|
||||
val legacyJars = currentNode.nodeDir / "legacy-jars"
|
||||
legacyJars.toFile().mkdir()
|
||||
|
||||
val jacksonDestination = legacyJars / "jackson-core.jar"
|
||||
val jacksonSource = smokeTestResource("jackson-core.jar")
|
||||
jacksonSource.copyTo(jacksonDestination)
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
@ -123,6 +133,18 @@ class ExternalVerificationSignedCordappsTest {
|
||||
oldRpc.startFlow(::IssueAndChangeNotaryFlow, notaryIdentities[0], notaryIdentities[1]).returnValue.getOrThrow()
|
||||
}
|
||||
|
||||
@Test(timeout = 300_000)
|
||||
fun `transaction containing 4_11 and 4_12 contract referencing Jackson dependency issued on new node`() {
|
||||
val issuanceStateRef = legacyJackonIssuance(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 cashIssuanceAndPayment(issuer: NodeProcess, recipient: NodeProcess): Pair<SignedTransaction, SignedTransaction> {
|
||||
val issuerRpc = issuer.connect(superUser).proxy
|
||||
val recipientRpc = recipient.connect(superUser).proxy
|
||||
|
39
legacy411/build.gradle
Normal file
39
legacy411/build.gradle
Normal file
@ -0,0 +1,39 @@
|
||||
apply plugin: 'org.jetbrains.kotlin.jvm'
|
||||
apply plugin: 'net.corda.plugins.quasar-utils'
|
||||
apply plugin: 'net.corda.plugins.cordapp'
|
||||
apply plugin: 'java'
|
||||
|
||||
compileJava {
|
||||
sourceCompatibility = '1.8'
|
||||
targetCompatibility = '1.8'
|
||||
}
|
||||
|
||||
description 'Legacy CorDapp for testing'
|
||||
|
||||
dependencies {
|
||||
cordaProvided("net.corda:corda-core:4.11") {
|
||||
exclude group: quasar_group, module: 'quasar-core'
|
||||
}
|
||||
cordaProvided configurations['quasar']
|
||||
cordaProvided "com.fasterxml.jackson.core:jackson-databind:$jackson_version"
|
||||
}
|
||||
|
||||
cordapp {
|
||||
targetPlatformVersion 1
|
||||
minimumPlatformVersion 1
|
||||
sealing {
|
||||
enabled false // This needs to be disabled for AttachmentsClassLoaderSerializationTests to work
|
||||
}
|
||||
contract {
|
||||
name "Legacy Test CorDapp"
|
||||
versionId 1
|
||||
vendor "R3"
|
||||
licence "Open Source (Apache 2)"
|
||||
}
|
||||
workflow {
|
||||
name "Legacy Test CorDapp"
|
||||
versionId 1
|
||||
vendor "R3"
|
||||
licence "Open Source (Apache 2)"
|
||||
}
|
||||
}
|
@ -0,0 +1,116 @@
|
||||
package net.corda.legacy.contracts;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
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 AnotherDummyContract implements Contract {
|
||||
@NotNull
|
||||
private final String magicString = "helloworld";
|
||||
@NotNull
|
||||
public static final String ANOTHER_DUMMY_PROGRAM_ID = "net.corda.legacy.contracts.AnotherDummyContract";
|
||||
|
||||
@NotNull
|
||||
public final String getMagicString() {
|
||||
return this.magicString;
|
||||
}
|
||||
|
||||
public void verify(@NotNull LedgerTransaction tx) {
|
||||
Intrinsics.checkNotNullParameter(tx, "tx");
|
||||
}
|
||||
|
||||
public void randomMethod() throws JsonProcessingException {
|
||||
throw new JsonProcessingException("") {
|
||||
};
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
39
legacy412/build.gradle
Normal file
39
legacy412/build.gradle
Normal file
@ -0,0 +1,39 @@
|
||||
apply plugin: 'org.jetbrains.kotlin.jvm'
|
||||
apply plugin: 'net.corda.plugins.quasar-utils'
|
||||
apply plugin: 'net.corda.plugins.cordapp'
|
||||
apply plugin: 'java'
|
||||
|
||||
compileJava {
|
||||
sourceCompatibility = '1.8'
|
||||
targetCompatibility = '1.8'
|
||||
}
|
||||
|
||||
description 'Legacy CorDapp for testing'
|
||||
|
||||
dependencies {
|
||||
cordaProvided("net.corda:corda-core:4.11") {
|
||||
exclude group: quasar_group, module: 'quasar-core'
|
||||
}
|
||||
cordaProvided configurations['quasar']
|
||||
cordaProvided "com.fasterxml.jackson.core:jackson-databind:$jackson_version"
|
||||
}
|
||||
|
||||
cordapp {
|
||||
targetPlatformVersion 1
|
||||
minimumPlatformVersion 1
|
||||
sealing {
|
||||
enabled false // This needs to be disabled for AttachmentsClassLoaderSerializationTests to work
|
||||
}
|
||||
contract {
|
||||
name "Legacy Test CorDapp"
|
||||
versionId 2
|
||||
vendor "R3"
|
||||
licence "Open Source (Apache 2)"
|
||||
}
|
||||
workflow {
|
||||
name "Legacy Test CorDapp"
|
||||
versionId 2
|
||||
vendor "R3"
|
||||
licence "Open Source (Apache 2)"
|
||||
}
|
||||
}
|
@ -0,0 +1,116 @@
|
||||
package net.corda.legacy.contracts;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
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 AnotherDummyContract implements Contract {
|
||||
@NotNull
|
||||
private final String magicString = "helloworld";
|
||||
@NotNull
|
||||
public static final String ANOTHER_DUMMY_PROGRAM_ID = "net.corda.legacy.contracts.AnotherDummyContract";
|
||||
|
||||
@NotNull
|
||||
public final String getMagicString() {
|
||||
return this.magicString;
|
||||
}
|
||||
|
||||
public void verify(@NotNull LedgerTransaction tx) {
|
||||
Intrinsics.checkNotNullParameter(tx, "tx");
|
||||
}
|
||||
|
||||
public void randomMethod() throws JsonProcessingException {
|
||||
throw new JsonProcessingException("") {
|
||||
};
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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.AnotherDummyContract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.security.SignatureException;
|
||||
|
||||
@StartableByRPC
|
||||
public final class LegacyIssuanceFlow extends FlowLogic {
|
||||
private final int magicNumber;
|
||||
|
||||
public LegacyIssuanceFlow(int magicNumber) {
|
||||
this.magicNumber = magicNumber;
|
||||
}
|
||||
|
||||
@Suspendable
|
||||
@NotNull
|
||||
public StateRef call() {
|
||||
ServiceHub var10000 = this.getServiceHub();
|
||||
AnotherDummyContract var10001 = new AnotherDummyContract();
|
||||
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();
|
||||
}
|
||||
}
|
@ -36,6 +36,7 @@ import net.corda.serialization.internal.verifier.ExternalVerifierOutbound.Verifi
|
||||
import net.corda.serialization.internal.verifier.ExternalVerifierOutbound.VerifierRequest.GetTrustedClassAttachments
|
||||
import net.corda.serialization.internal.verifier.readCordaSerializable
|
||||
import net.corda.serialization.internal.verifier.writeCordaSerializable
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.lang.Character.MAX_RADIX
|
||||
import java.lang.ProcessBuilder.Redirect
|
||||
@ -206,9 +207,18 @@ class ExternalVerifierHandleImpl(
|
||||
val command = ArrayList<String>()
|
||||
command += "${Path(System.getProperty("java.home"), "bin", "java")}"
|
||||
command += inheritedJvmArgs
|
||||
|
||||
// Build list of 3rd party jars
|
||||
val legacyJarsPath = baseDirectory / "legacy-jars"
|
||||
val extraClassPath = legacyJarsPath.toFile().listFiles { _, name ->
|
||||
name.endsWith(".jar")
|
||||
}?.joinToString(File.pathSeparator, File.pathSeparator)
|
||||
val classpath = if (extraClassPath == null) "$verifierJar" else "$verifierJar$extraClassPath"
|
||||
|
||||
command += listOf(
|
||||
"-jar",
|
||||
"$verifierJar",
|
||||
"-cp",
|
||||
classpath,
|
||||
"net.corda.verifier.Main",
|
||||
socketFile.absolutePathString(),
|
||||
log.level.name.lowercase()
|
||||
)
|
||||
|
@ -44,6 +44,8 @@ include 'finance:workflows'
|
||||
include 'core'
|
||||
include 'core-1.2'
|
||||
include 'core-tests'
|
||||
include 'legacy411'
|
||||
include 'legacy412'
|
||||
include 'docs'
|
||||
include 'node-api'
|
||||
include 'node-api-tests'
|
||||
|
Loading…
Reference in New Issue
Block a user