mirror of
https://github.com/corda/corda.git
synced 2024-12-23 23:02:29 +00:00
CORDA-3750: Reimplement Corda's Crypto object for use inside the sandbox. (#6193)
* CORDA-3750: Use hand-written sandbox Crypto object that delegates to the node. * CORDA-3750: Add integration test for deterministic CashIssueAndPayment flow. * Tidy up generics for Array instances. * Upgrade to DJVM 1.1-RC04.
This commit is contained in:
parent
4ed57506c8
commit
6ebc6e9b16
@ -30,7 +30,7 @@ snakeYamlVersion=1.19
|
|||||||
caffeineVersion=2.7.0
|
caffeineVersion=2.7.0
|
||||||
metricsVersion=4.1.0
|
metricsVersion=4.1.0
|
||||||
metricsNewRelicVersion=1.1.1
|
metricsNewRelicVersion=1.1.1
|
||||||
djvmVersion=1.1-RC03
|
djvmVersion=1.1-RC04
|
||||||
deterministicRtVersion=1.0-RC02
|
deterministicRtVersion=1.0-RC02
|
||||||
openSourceBranch=https://github.com/corda/corda/blob/release/os/4.4
|
openSourceBranch=https://github.com/corda/corda/blob/release/os/4.4
|
||||||
openSourceSamplesBranch=https://github.com/corda/samples/blob/release-V4
|
openSourceSamplesBranch=https://github.com/corda/samples/blob/release-V4
|
||||||
|
@ -304,6 +304,11 @@ quasar {
|
|||||||
|
|
||||||
jar {
|
jar {
|
||||||
baseName 'corda-node'
|
baseName 'corda-node'
|
||||||
|
exclude 'sandbox/java/**'
|
||||||
|
exclude 'sandbox/org/**'
|
||||||
|
exclude 'sandbox/net/corda/core/crypto/SecureHash.class'
|
||||||
|
exclude 'sandbox/net/corda/core/crypto/SignatureScheme.class'
|
||||||
|
exclude 'sandbox/net/corda/core/crypto/TransactionSignature.class'
|
||||||
manifest {
|
manifest {
|
||||||
attributes('Corda-Deterministic-Runtime': configurations.jdkRt.singleFile.name)
|
attributes('Corda-Deterministic-Runtime': configurations.jdkRt.singleFile.name)
|
||||||
attributes('Corda-Deterministic-Classpath': configurations.deterministic.collect { it.name }.join(' '))
|
attributes('Corda-Deterministic-Classpath': configurations.deterministic.collect { it.name }.join(' '))
|
||||||
|
@ -27,12 +27,12 @@ private const val TX_PRIVACY_SALT = 7
|
|||||||
private const val TX_NETWORK_PARAMETERS = 8
|
private const val TX_NETWORK_PARAMETERS = 8
|
||||||
private const val TX_REFERENCES = 9
|
private const val TX_REFERENCES = 9
|
||||||
|
|
||||||
class LtxFactory : Function<Array<Any?>, LedgerTransaction> {
|
class LtxFactory : Function<Array<out Any?>, LedgerTransaction> {
|
||||||
|
|
||||||
@Suppress("unchecked_cast")
|
@Suppress("unchecked_cast")
|
||||||
override fun apply(txArgs: Array<Any?>): LedgerTransaction {
|
override fun apply(txArgs: Array<out Any?>): LedgerTransaction {
|
||||||
return LedgerTransaction.createForSandbox(
|
return LedgerTransaction.createForSandbox(
|
||||||
inputs = (txArgs[TX_INPUTS] as Array<Array<Any?>>).map { it.toStateAndRef() },
|
inputs = (txArgs[TX_INPUTS] as Array<Array<out Any?>>).map { it.toStateAndRef() },
|
||||||
outputs = (txArgs[TX_OUTPUTS] as? List<TransactionState<ContractState>>) ?: emptyList(),
|
outputs = (txArgs[TX_OUTPUTS] as? List<TransactionState<ContractState>>) ?: emptyList(),
|
||||||
commands = (txArgs[TX_COMMANDS] as? List<CommandWithParties<CommandData>>) ?: emptyList(),
|
commands = (txArgs[TX_COMMANDS] as? List<CommandWithParties<CommandData>>) ?: emptyList(),
|
||||||
attachments = (txArgs[TX_ATTACHMENTS] as? List<Attachment>) ?: emptyList(),
|
attachments = (txArgs[TX_ATTACHMENTS] as? List<Attachment>) ?: emptyList(),
|
||||||
@ -41,7 +41,7 @@ class LtxFactory : Function<Array<Any?>, LedgerTransaction> {
|
|||||||
timeWindow = txArgs[TX_TIME_WINDOW] as? TimeWindow,
|
timeWindow = txArgs[TX_TIME_WINDOW] as? TimeWindow,
|
||||||
privacySalt = txArgs[TX_PRIVACY_SALT] as PrivacySalt,
|
privacySalt = txArgs[TX_PRIVACY_SALT] as PrivacySalt,
|
||||||
networkParameters = txArgs[TX_NETWORK_PARAMETERS] as NetworkParameters,
|
networkParameters = txArgs[TX_NETWORK_PARAMETERS] as NetworkParameters,
|
||||||
references = (txArgs[TX_REFERENCES] as Array<Array<Any?>>).map { it.toStateAndRef() }
|
references = (txArgs[TX_REFERENCES] as Array<Array<out Any?>>).map { it.toStateAndRef() }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
package net.corda.node.services
|
||||||
|
|
||||||
|
import net.corda.core.messaging.startFlow
|
||||||
|
import net.corda.core.utilities.OpaqueBytes
|
||||||
|
import net.corda.core.utilities.getOrThrow
|
||||||
|
import net.corda.core.utilities.loggerFor
|
||||||
|
import net.corda.finance.DOLLARS
|
||||||
|
import net.corda.finance.flows.CashIssueAndPaymentFlow
|
||||||
|
import net.corda.node.DeterministicSourcesRule
|
||||||
|
import net.corda.testing.core.ALICE_NAME
|
||||||
|
import net.corda.testing.core.DUMMY_NOTARY_NAME
|
||||||
|
import net.corda.testing.core.singleIdentity
|
||||||
|
import net.corda.testing.driver.DriverParameters
|
||||||
|
import net.corda.testing.driver.driver
|
||||||
|
import net.corda.testing.driver.internal.incrementalPortAllocation
|
||||||
|
import net.corda.testing.node.NotarySpec
|
||||||
|
import net.corda.testing.node.internal.findCordapp
|
||||||
|
import org.junit.ClassRule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.jupiter.api.assertDoesNotThrow
|
||||||
|
|
||||||
|
@Suppress("FunctionName")
|
||||||
|
class DeterministicCashIssueAndPaymentTest {
|
||||||
|
companion object {
|
||||||
|
val logger = loggerFor<DeterministicCashIssueAndPaymentTest>()
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
@JvmField
|
||||||
|
val djvmSources = DeterministicSourcesRule()
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val CASH_AMOUNT = 500.DOLLARS
|
||||||
|
|
||||||
|
fun parametersFor(djvmSources: DeterministicSourcesRule): DriverParameters {
|
||||||
|
return DriverParameters(
|
||||||
|
portAllocation = incrementalPortAllocation(),
|
||||||
|
startNodesInProcess = false,
|
||||||
|
notarySpecs = listOf(NotarySpec(DUMMY_NOTARY_NAME, validating = true)),
|
||||||
|
cordappsForAllNodes = listOf(
|
||||||
|
findCordapp("net.corda.finance.contracts"),
|
||||||
|
findCordapp("net.corda.finance.workflows")
|
||||||
|
),
|
||||||
|
djvmBootstrapSource = djvmSources.bootstrap,
|
||||||
|
djvmCordaSource = djvmSources.corda
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(timeout = 300_000)
|
||||||
|
fun `test DJVM can issue cash`() {
|
||||||
|
val reference = OpaqueBytes.of(0x01)
|
||||||
|
driver(parametersFor(djvmSources)) {
|
||||||
|
val alice = startNode(providedName = ALICE_NAME).getOrThrow()
|
||||||
|
val aliceParty = alice.nodeInfo.singleIdentity()
|
||||||
|
val notaryParty = notaryHandles.single().identity
|
||||||
|
val txId = assertDoesNotThrow {
|
||||||
|
alice.rpc.startFlow(::CashIssueAndPaymentFlow,
|
||||||
|
CASH_AMOUNT,
|
||||||
|
reference,
|
||||||
|
aliceParty,
|
||||||
|
false,
|
||||||
|
notaryParty
|
||||||
|
).returnValue.getOrThrow()
|
||||||
|
}
|
||||||
|
logger.info("TX-ID: {}", txId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
8
node/src/main/java/sandbox/java/lang/CharSequence.java
Normal file
8
node/src/main/java/sandbox/java/lang/CharSequence.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package sandbox.java.lang;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy class that implements just enough of {@link java.lang.CharSequence}
|
||||||
|
* to allow us to compile {@link sandbox.net.corda.core.crypto.Crypto}.
|
||||||
|
*/
|
||||||
|
public interface CharSequence extends java.lang.CharSequence {
|
||||||
|
}
|
8
node/src/main/java/sandbox/java/lang/Comparable.java
Normal file
8
node/src/main/java/sandbox/java/lang/Comparable.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package sandbox.java.lang;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy class that implements just enough of {@link java.lang.Comparable}
|
||||||
|
* to allow us to compile {@link sandbox.net.corda.core.crypto.Crypto}.
|
||||||
|
*/
|
||||||
|
public interface Comparable<T> extends java.lang.Comparable<T> {
|
||||||
|
}
|
8
node/src/main/java/sandbox/java/lang/Number.java
Normal file
8
node/src/main/java/sandbox/java/lang/Number.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package sandbox.java.lang;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy class that implements just enough of {@link java.lang.Number}
|
||||||
|
* to allow us to compile {@link sandbox.net.corda.core.crypto.Crypto}.
|
||||||
|
*/
|
||||||
|
public class Number extends Object {
|
||||||
|
}
|
8
node/src/main/java/sandbox/java/math/BigInteger.java
Normal file
8
node/src/main/java/sandbox/java/math/BigInteger.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package sandbox.java.math;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy class that implements just enough of {@link java.math.BigInteger}
|
||||||
|
* to allow us to compile {@link sandbox.net.corda.core.crypto.Crypto}.
|
||||||
|
*/
|
||||||
|
public class BigInteger extends sandbox.java.lang.Number {
|
||||||
|
}
|
13
node/src/main/java/sandbox/java/security/Key.java
Normal file
13
node/src/main/java/sandbox/java/security/Key.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package sandbox.java.security;
|
||||||
|
|
||||||
|
import sandbox.java.lang.String;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy class that implements just enough of {@link java.security.Key}
|
||||||
|
* to allow us to compile {@link sandbox.net.corda.core.crypto.Crypto}.
|
||||||
|
*/
|
||||||
|
public interface Key {
|
||||||
|
String getAlgorithm();
|
||||||
|
String getFormat();
|
||||||
|
byte[] getEncoded();
|
||||||
|
}
|
8
node/src/main/java/sandbox/java/security/KeyPair.java
Normal file
8
node/src/main/java/sandbox/java/security/KeyPair.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package sandbox.java.security;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy class that implements just enough of {@link java.security.KeyPair}
|
||||||
|
* to allow us to compile {@link sandbox.net.corda.core.crypto.Crypto}.
|
||||||
|
*/
|
||||||
|
public final class KeyPair extends sandbox.java.lang.Object implements java.io.Serializable {
|
||||||
|
}
|
8
node/src/main/java/sandbox/java/security/PrivateKey.java
Normal file
8
node/src/main/java/sandbox/java/security/PrivateKey.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package sandbox.java.security;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy class that implements just enough of {@link java.security.PrivateKey}
|
||||||
|
* to allow us to compile {@link sandbox.net.corda.core.crypto.Crypto}.
|
||||||
|
*/
|
||||||
|
public interface PrivateKey extends Key {
|
||||||
|
}
|
8
node/src/main/java/sandbox/java/security/PublicKey.java
Normal file
8
node/src/main/java/sandbox/java/security/PublicKey.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package sandbox.java.security;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy class that implements just enough of {@link java.security.PublicKey}
|
||||||
|
* to allow us to compile {@link sandbox.net.corda.core.crypto.Crypto}.
|
||||||
|
*/
|
||||||
|
public interface PublicKey extends Key {
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package sandbox.java.security.spec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy class that implements just enough of {@link java.security.spec.AlgorithmParameterSpec}
|
||||||
|
* to allow us to compile {@link sandbox.net.corda.core.crypto.Crypto}.
|
||||||
|
*/
|
||||||
|
public interface AlgorithmParameterSpec {
|
||||||
|
}
|
16
node/src/main/java/sandbox/java/util/ArrayList.java
Normal file
16
node/src/main/java/sandbox/java/util/ArrayList.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package sandbox.java.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy class that implements just enough of {@link java.util.ArrayList}
|
||||||
|
* to allow us to compile {@link sandbox.net.corda.core.crypto.Crypto}.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class ArrayList<T> extends sandbox.java.lang.Object implements List<T> {
|
||||||
|
public ArrayList(int size) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean add(T item) {
|
||||||
|
throw new UnsupportedOperationException("Dummy class - not implemented");
|
||||||
|
}
|
||||||
|
}
|
9
node/src/main/java/sandbox/java/util/List.java
Normal file
9
node/src/main/java/sandbox/java/util/List.java
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package sandbox.java.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy class that implements just enough of {@link java.util.List}
|
||||||
|
* to allow us to compile {@link sandbox.net.corda.core.crypto.Crypto}.
|
||||||
|
*/
|
||||||
|
public interface List<T> {
|
||||||
|
boolean add(T item);
|
||||||
|
}
|
62
node/src/main/java/sandbox/net/corda/core/crypto/DJVM.java
Normal file
62
node/src/main/java/sandbox/net/corda/core/crypto/DJVM.java
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package sandbox.net.corda.core.crypto;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import sandbox.java.lang.Integer;
|
||||||
|
import sandbox.java.lang.String;
|
||||||
|
import sandbox.java.util.ArrayList;
|
||||||
|
import sandbox.java.util.List;
|
||||||
|
import sandbox.org.bouncycastle.asn1.x509.AlgorithmIdentifier;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class for {@link sandbox.net.corda.core.crypto.Crypto}.
|
||||||
|
* Deliberately package-private.
|
||||||
|
*/
|
||||||
|
final class DJVM {
|
||||||
|
private DJVM() {}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
static SignatureScheme toDJVM(@NotNull net.corda.core.crypto.SignatureScheme scheme) {
|
||||||
|
// The AlgorithmParameterSpec is deliberately left as null
|
||||||
|
// because it is computationally expensive to generate these
|
||||||
|
// objects inside the sandbox every time.
|
||||||
|
return new SignatureScheme(
|
||||||
|
scheme.getSchemeNumberID(),
|
||||||
|
String.toDJVM(scheme.getSchemeCodeName()),
|
||||||
|
toDJVM(scheme.getSignatureOID()),
|
||||||
|
toDJVM(scheme.getAlternativeOIDs()),
|
||||||
|
String.toDJVM(scheme.getProviderName()),
|
||||||
|
String.toDJVM(scheme.getAlgorithmName()),
|
||||||
|
String.toDJVM(scheme.getSignatureName()),
|
||||||
|
null,
|
||||||
|
Integer.toDJVM(scheme.getKeySize()),
|
||||||
|
String.toDJVM(scheme.getDesc())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static org.bouncycastle.asn1.x509.AlgorithmIdentifier fromDJVM(@NotNull AlgorithmIdentifier oid) {
|
||||||
|
try {
|
||||||
|
return org.bouncycastle.asn1.x509.AlgorithmIdentifier.getInstance(oid.getEncoded());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw sandbox.java.lang.DJVM.toRuleViolationError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static AlgorithmIdentifier toDJVM(@NotNull org.bouncycastle.asn1.x509.AlgorithmIdentifier oid) {
|
||||||
|
try {
|
||||||
|
return AlgorithmIdentifier.getInstance(oid.getEncoded());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw sandbox.java.lang.DJVM.toRuleViolationError(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
static List<AlgorithmIdentifier> toDJVM(@NotNull java.util.List<org.bouncycastle.asn1.x509.AlgorithmIdentifier> list) {
|
||||||
|
ArrayList<AlgorithmIdentifier> djvmList = new ArrayList<>(list.size());
|
||||||
|
for (org.bouncycastle.asn1.x509.AlgorithmIdentifier oid : list) {
|
||||||
|
djvmList.add(toDJVM(oid));
|
||||||
|
}
|
||||||
|
return djvmList;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package sandbox.net.corda.core.crypto;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import sandbox.java.lang.Object;
|
||||||
|
import sandbox.java.lang.String;
|
||||||
|
import sandbox.java.security.PublicKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We shall delegate as much cryptography as possible to Corda's
|
||||||
|
* underlying {@link net.corda.core.crypto.Crypto} object and its
|
||||||
|
* {@link java.security.Provider} classes. This wrapper only needs
|
||||||
|
* to implement {@link #equals} and {@link #hashCode}.
|
||||||
|
*/
|
||||||
|
final class DJVMPublicKey extends Object implements PublicKey {
|
||||||
|
private final java.security.PublicKey underlying;
|
||||||
|
private final String algorithm;
|
||||||
|
private final String format;
|
||||||
|
private final int hashCode;
|
||||||
|
|
||||||
|
DJVMPublicKey(@NotNull java.security.PublicKey underlying) {
|
||||||
|
this.underlying = underlying;
|
||||||
|
this.algorithm = String.toDJVM(underlying.getAlgorithm());
|
||||||
|
this.format = String.toDJVM(underlying.getFormat());
|
||||||
|
this.hashCode = underlying.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
java.security.PublicKey getUnderlying() {
|
||||||
|
return underlying;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(java.lang.Object other) {
|
||||||
|
if (this == other) {
|
||||||
|
return true;
|
||||||
|
} else if (!(other instanceof DJVMPublicKey)) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return underlying.equals(((DJVMPublicKey) other).underlying);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAlgorithm() {
|
||||||
|
return algorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFormat() {
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getEncoded() {
|
||||||
|
return underlying.getEncoded();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package sandbox.org.bouncycastle.asn1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy class that implements just enough of {@link org.bouncycastle.asn1.ASN1Encodable}
|
||||||
|
* to allow us to compile {@link sandbox.net.corda.core.crypto.Crypto}.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("WeakerAccess")
|
||||||
|
public interface ASN1Encodable {
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
package sandbox.org.bouncycastle.asn1;
|
||||||
|
|
||||||
|
import sandbox.java.lang.Object;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy class that implements just enough of {@link org.bouncycastle.asn1.ASN1Object}
|
||||||
|
* to allow us to compile {@link sandbox.net.corda.core.crypto.Crypto}.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("RedundantThrows")
|
||||||
|
public class ASN1Object extends Object implements ASN1Encodable {
|
||||||
|
public byte[] getEncoded() throws IOException {
|
||||||
|
throw new UnsupportedOperationException("Dummy class - not implemented");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package sandbox.org.bouncycastle.asn1.x509;
|
||||||
|
|
||||||
|
import sandbox.org.bouncycastle.asn1.ASN1Object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy class that implements just enough of {@link org.bouncycastle.asn1.x509.AlgorithmIdentifier}
|
||||||
|
* to allow us to compile {@link sandbox.net.corda.core.crypto.Crypto}.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class AlgorithmIdentifier extends ASN1Object {
|
||||||
|
public static AlgorithmIdentifier getInstance(Object obj) {
|
||||||
|
throw new UnsupportedOperationException("Dummy class - not implemented");
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package sandbox.org.bouncycastle.asn1.x509;
|
||||||
|
|
||||||
|
import sandbox.org.bouncycastle.asn1.ASN1Object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy class that implements just enough of {@link org.bouncycastle.asn1.x509.SubjectPublicKeyInfo}
|
||||||
|
* to allow us to compile {@link sandbox.net.corda.core.crypto.Crypto}.
|
||||||
|
*/
|
||||||
|
public class SubjectPublicKeyInfo extends ASN1Object {
|
||||||
|
}
|
@ -31,7 +31,7 @@ class Serializer(
|
|||||||
* [net.corda.node.djvm.LtxFactory] to be transformed finally to
|
* [net.corda.node.djvm.LtxFactory] to be transformed finally to
|
||||||
* a list of [net.corda.core.contracts.StateAndRef] objects,
|
* a list of [net.corda.core.contracts.StateAndRef] objects,
|
||||||
*/
|
*/
|
||||||
fun deserialize(stateRefs: List<SerializedStateAndRef>): Array<Array<Any?>> {
|
fun deserialize(stateRefs: List<SerializedStateAndRef>): Array<Array<out Any?>> {
|
||||||
return stateRefs.map {
|
return stateRefs.map {
|
||||||
arrayOf(deserialize(it.serializedState), deserialize(it.ref.serialize()))
|
arrayOf(deserialize(it.serializedState), deserialize(it.ref.serialize()))
|
||||||
}.toTypedArray()
|
}.toTypedArray()
|
||||||
|
@ -47,7 +47,20 @@ class DeterministicVerifierFactoryService(
|
|||||||
ConstructorForDeserialization::class.java,
|
ConstructorForDeserialization::class.java,
|
||||||
DeprecatedConstructorForDeserialization::class.java
|
DeprecatedConstructorForDeserialization::class.java
|
||||||
),
|
),
|
||||||
bootstrapSource = bootstrapSource
|
bootstrapSource = bootstrapSource,
|
||||||
|
overrideClasses = setOf(
|
||||||
|
/**
|
||||||
|
* These classes are all duplicated into the sandbox
|
||||||
|
* without the DJVM modifying their byte-code first.
|
||||||
|
* The goal is to delegate cryptographic operations
|
||||||
|
* out to the Node rather than perform them inside
|
||||||
|
* the sandbox, because this is MUCH FASTER.
|
||||||
|
*/
|
||||||
|
sandbox.net.corda.core.crypto.Crypto::class.java.name,
|
||||||
|
"sandbox.net.corda.core.crypto.DJVM",
|
||||||
|
"sandbox.net.corda.core.crypto.DJVMPublicKey",
|
||||||
|
"sandbox.net.corda.core.crypto.internal.ProviderMapKt"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
baseSandboxConfiguration = SandboxConfiguration.createFor(
|
baseSandboxConfiguration = SandboxConfiguration.createFor(
|
||||||
|
261
node/src/main/kotlin/sandbox/net/corda/core/crypto/Crypto.kt
Normal file
261
node/src/main/kotlin/sandbox/net/corda/core/crypto/Crypto.kt
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
package sandbox.net.corda.core.crypto
|
||||||
|
|
||||||
|
import sandbox.net.corda.core.crypto.DJVM.fromDJVM
|
||||||
|
import sandbox.net.corda.core.crypto.DJVM.toDJVM
|
||||||
|
import sandbox.java.lang.String
|
||||||
|
import sandbox.java.lang.doCatch
|
||||||
|
import sandbox.java.math.BigInteger
|
||||||
|
import sandbox.java.security.KeyPair
|
||||||
|
import sandbox.java.security.PrivateKey
|
||||||
|
import sandbox.java.security.PublicKey
|
||||||
|
import sandbox.java.util.ArrayList
|
||||||
|
import sandbox.java.util.List
|
||||||
|
import sandbox.java.lang.Object
|
||||||
|
import sandbox.org.bouncycastle.asn1.x509.AlgorithmIdentifier
|
||||||
|
import sandbox.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
|
||||||
|
import java.security.GeneralSecurityException
|
||||||
|
import java.security.SignatureException
|
||||||
|
import java.security.spec.InvalidKeySpecException
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a hand-written "drop-in" replacement for the version of
|
||||||
|
* [net.corda.core.crypto.Crypto] found inside core-deterministic.
|
||||||
|
* This class is used in the DJVM sandbox instead of transforming
|
||||||
|
* the byte-code for [net.corda.core.crypto.Crypto], with the goal
|
||||||
|
* of not needing to instantiate some EXPENSIVE elliptic curve
|
||||||
|
* cryptography classes inside every single sandbox.
|
||||||
|
*
|
||||||
|
* The downside is that this class MUST manually be kept consistent
|
||||||
|
* with the DJVM's byte-code rewriting rules.
|
||||||
|
*/
|
||||||
|
@Suppress("unused", "unused_parameter", "TooManyFunctions")
|
||||||
|
object Crypto : Object() {
|
||||||
|
@JvmField
|
||||||
|
val RSA_SHA256: SignatureScheme = toDJVM(net.corda.core.crypto.Crypto.RSA_SHA256)
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val ECDSA_SECP256K1_SHA256: SignatureScheme = toDJVM(net.corda.core.crypto.Crypto.ECDSA_SECP256K1_SHA256)
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val ECDSA_SECP256R1_SHA256: SignatureScheme = toDJVM(net.corda.core.crypto.Crypto.ECDSA_SECP256R1_SHA256)
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val EDDSA_ED25519_SHA512: SignatureScheme = toDJVM(net.corda.core.crypto.Crypto.EDDSA_ED25519_SHA512)
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val SPHINCS256_SHA256: SignatureScheme = toDJVM(net.corda.core.crypto.Crypto.SPHINCS256_SHA256)
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val COMPOSITE_KEY: SignatureScheme = toDJVM(net.corda.core.crypto.Crypto.COMPOSITE_KEY)
|
||||||
|
|
||||||
|
@JvmField
|
||||||
|
val DEFAULT_SIGNATURE_SCHEME = EDDSA_ED25519_SHA512
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We can use the unsandboxed versions of [Map] and [List] here
|
||||||
|
* because the [underlyingSchemes] and [djvmSchemes] fields are
|
||||||
|
* private and not exposed to the rest of the sandbox.
|
||||||
|
*/
|
||||||
|
private val underlyingSchemes: Map<kotlin.String, net.corda.core.crypto.SignatureScheme>
|
||||||
|
= net.corda.core.crypto.Crypto.supportedSignatureSchemes()
|
||||||
|
.associateBy(net.corda.core.crypto.SignatureScheme::schemeCodeName)
|
||||||
|
private val djvmSchemes: Map<String, SignatureScheme> = listOf(
|
||||||
|
RSA_SHA256,
|
||||||
|
ECDSA_SECP256K1_SHA256,
|
||||||
|
ECDSA_SECP256R1_SHA256,
|
||||||
|
EDDSA_ED25519_SHA512,
|
||||||
|
SPHINCS256_SHA256,
|
||||||
|
COMPOSITE_KEY
|
||||||
|
).associateByTo(LinkedHashMap(), SignatureScheme::schemeCodeName)
|
||||||
|
|
||||||
|
private fun findUnderlyingSignatureScheme(signatureScheme: SignatureScheme): net.corda.core.crypto.SignatureScheme {
|
||||||
|
return net.corda.core.crypto.Crypto.findSignatureScheme(String.fromDJVM(signatureScheme.schemeCodeName))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PublicKey.toUnderlyingKey(): java.security.PublicKey {
|
||||||
|
return (this as? DJVMPublicKey ?: throw sandbox.java.lang.fail("Unsupported key ${this::class.java.name}")).underlying
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun supportedSignatureSchemes(): List<SignatureScheme> {
|
||||||
|
val schemes = ArrayList<SignatureScheme>(djvmSchemes.size)
|
||||||
|
for (scheme in djvmSchemes.values) {
|
||||||
|
schemes.add(scheme)
|
||||||
|
}
|
||||||
|
return schemes
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun isSupportedSignatureScheme(signatureScheme: SignatureScheme): Boolean {
|
||||||
|
return String.fromDJVM(signatureScheme.schemeCodeName) in underlyingSchemes
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun findSignatureScheme(schemeCodeName: String): SignatureScheme {
|
||||||
|
return djvmSchemes[schemeCodeName]
|
||||||
|
?: throw IllegalArgumentException("Unsupported key/algorithm for schemeCodeName: $schemeCodeName")
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun findSignatureScheme(schemeNumberID: Int): SignatureScheme {
|
||||||
|
val underlyingScheme = net.corda.core.crypto.Crypto.findSignatureScheme(schemeNumberID)
|
||||||
|
return findSignatureScheme(String.toDJVM(underlyingScheme.schemeCodeName))
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun findSignatureScheme(key: PublicKey): SignatureScheme {
|
||||||
|
val underlyingScheme = net.corda.core.crypto.Crypto.findSignatureScheme(key.toUnderlyingKey())
|
||||||
|
return findSignatureScheme(String.toDJVM(underlyingScheme.schemeCodeName))
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun findSignatureScheme(algorithm: AlgorithmIdentifier): SignatureScheme {
|
||||||
|
val underlyingScheme = net.corda.core.crypto.Crypto.findSignatureScheme(fromDJVM(algorithm))
|
||||||
|
return findSignatureScheme(String.toDJVM(underlyingScheme.schemeCodeName))
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun findSignatureScheme(key: PrivateKey): SignatureScheme {
|
||||||
|
throw sandbox.java.lang.failApi("Crypto.findSignatureScheme(PrivateKey)")
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun decodePrivateKey(signatureScheme: SignatureScheme, encodedKey: ByteArray): PrivateKey {
|
||||||
|
throw sandbox.java.lang.failApi("Crypto.decodePrivateKey(SignatureScheme, byte[])")
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun decodePublicKey(encodedKey: ByteArray): PublicKey {
|
||||||
|
val underlying = try {
|
||||||
|
net.corda.core.crypto.Crypto.decodePublicKey(encodedKey)
|
||||||
|
} catch (e: InvalidKeySpecException) {
|
||||||
|
throw sandbox.java.lang.fromDJVM(doCatch(e))
|
||||||
|
}
|
||||||
|
return DJVMPublicKey(underlying)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun decodePublicKey(schemeCodeName: String, encodedKey: ByteArray): PublicKey {
|
||||||
|
val underlying = try {
|
||||||
|
net.corda.core.crypto.Crypto.decodePublicKey(String.fromDJVM(schemeCodeName), encodedKey)
|
||||||
|
} catch (e: InvalidKeySpecException) {
|
||||||
|
throw sandbox.java.lang.fromDJVM(doCatch(e))
|
||||||
|
}
|
||||||
|
return DJVMPublicKey(underlying)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun decodePublicKey(signatureScheme: SignatureScheme, encodedKey: ByteArray): PublicKey {
|
||||||
|
return decodePublicKey(signatureScheme.schemeCodeName, encodedKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun deriveKeyPair(signatureScheme: SignatureScheme, privateKey: PrivateKey, seed: ByteArray): KeyPair {
|
||||||
|
throw sandbox.java.lang.failApi("Crypto.deriveKeyPair(SignatureScheme, PrivateKey, byte[])")
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun deriveKeyPair(privateKey: PrivateKey, seed: ByteArray): KeyPair {
|
||||||
|
throw sandbox.java.lang.failApi("Crypto.deriveKeyPair(PrivateKey, byte[])")
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun deriveKeyPairFromEntropy(signatureScheme: SignatureScheme, entropy: BigInteger): KeyPair {
|
||||||
|
throw sandbox.java.lang.failApi("Crypto.deriveKeyPairFromEntropy(SignatureScheme, BigInteger)")
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun deriveKeyPairFromEntropy(entropy: BigInteger): KeyPair {
|
||||||
|
throw sandbox.java.lang.failApi("Crypto.deriveKeyPairFromEntropy(BigInteger)")
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun doVerify(schemeCodeName: String, publicKey: PublicKey, signatureData: ByteArray, clearData: ByteArray): Boolean {
|
||||||
|
val underlyingKey = publicKey.toUnderlyingKey()
|
||||||
|
return try {
|
||||||
|
net.corda.core.crypto.Crypto.doVerify(String.fromDJVM(schemeCodeName), underlyingKey, signatureData, clearData)
|
||||||
|
} catch (e: GeneralSecurityException) {
|
||||||
|
throw sandbox.java.lang.fromDJVM(doCatch(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun doVerify(publicKey: PublicKey, signatureData: ByteArray, clearData: ByteArray): Boolean {
|
||||||
|
val underlyingKey = publicKey.toUnderlyingKey()
|
||||||
|
return try {
|
||||||
|
net.corda.core.crypto.Crypto.doVerify(underlyingKey, signatureData, clearData)
|
||||||
|
} catch (e: GeneralSecurityException) {
|
||||||
|
throw sandbox.java.lang.fromDJVM(doCatch(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun doVerify(signatureScheme: SignatureScheme, publicKey: PublicKey, signatureData: ByteArray, clearData: ByteArray): Boolean {
|
||||||
|
val underlyingScheme = findUnderlyingSignatureScheme(signatureScheme)
|
||||||
|
val underlyingKey = publicKey.toUnderlyingKey()
|
||||||
|
return try {
|
||||||
|
net.corda.core.crypto.Crypto.doVerify(underlyingScheme, underlyingKey, signatureData, clearData)
|
||||||
|
} catch (e: GeneralSecurityException) {
|
||||||
|
throw sandbox.java.lang.fromDJVM(doCatch(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun doVerify(txId: SecureHash, transactionSignature: TransactionSignature): Boolean {
|
||||||
|
throw sandbox.java.lang.failApi("Crypto.doVerify(SecureHash, TransactionSignature)")
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun isValid(txId: SecureHash, transactionSignature: TransactionSignature): Boolean {
|
||||||
|
throw sandbox.java.lang.failApi("Crypto.isValid(SecureHash, TransactionSignature)")
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun isValid(publicKey: PublicKey, signatureData: ByteArray, clearData: ByteArray): Boolean {
|
||||||
|
val underlyingKey = publicKey.toUnderlyingKey()
|
||||||
|
return try {
|
||||||
|
net.corda.core.crypto.Crypto.isValid(underlyingKey, signatureData, clearData)
|
||||||
|
} catch (e: SignatureException) {
|
||||||
|
throw sandbox.java.lang.fromDJVM(doCatch(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun isValid(signatureScheme: SignatureScheme, publicKey: PublicKey, signatureData: ByteArray, clearData: ByteArray): Boolean {
|
||||||
|
val underlyingScheme = findUnderlyingSignatureScheme(signatureScheme)
|
||||||
|
val underlyingKey = publicKey.toUnderlyingKey()
|
||||||
|
return try {
|
||||||
|
net.corda.core.crypto.Crypto.isValid(underlyingScheme, underlyingKey, signatureData, clearData)
|
||||||
|
} catch (e: SignatureException) {
|
||||||
|
throw sandbox.java.lang.fromDJVM(doCatch(e))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun publicKeyOnCurve(signatureScheme: SignatureScheme, publicKey: PublicKey): Boolean {
|
||||||
|
val underlyingScheme = findUnderlyingSignatureScheme(signatureScheme)
|
||||||
|
val underlyingKey = publicKey.toUnderlyingKey()
|
||||||
|
return net.corda.core.crypto.Crypto.publicKeyOnCurve(underlyingScheme, underlyingKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun validatePublicKey(key: PublicKey): Boolean {
|
||||||
|
return net.corda.core.crypto.Crypto.validatePublicKey(key.toUnderlyingKey())
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun toSupportedPublicKey(key: SubjectPublicKeyInfo): PublicKey {
|
||||||
|
return decodePublicKey(key.encoded)
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun toSupportedPublicKey(key: PublicKey): PublicKey {
|
||||||
|
val underlyingKey = key.toUnderlyingKey()
|
||||||
|
val supportedKey = net.corda.core.crypto.Crypto.toSupportedPublicKey(underlyingKey)
|
||||||
|
return if (supportedKey === underlyingKey) {
|
||||||
|
key
|
||||||
|
} else {
|
||||||
|
DJVMPublicKey(supportedKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
package sandbox.net.corda.core.crypto
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy class that implements just enough of [net.corda.core.crypto.SecureHash]
|
||||||
|
* to allow us to compile [sandbox.net.corda.core.crypto.Crypto].
|
||||||
|
*/
|
||||||
|
@Suppress("unused_parameter")
|
||||||
|
sealed class SecureHash(bytes: ByteArray) : sandbox.java.lang.Object()
|
@ -0,0 +1,26 @@
|
|||||||
|
package sandbox.net.corda.core.crypto
|
||||||
|
|
||||||
|
import sandbox.java.lang.String
|
||||||
|
import sandbox.java.lang.Integer
|
||||||
|
import sandbox.java.lang.Object
|
||||||
|
import sandbox.java.security.spec.AlgorithmParameterSpec
|
||||||
|
import sandbox.java.util.List
|
||||||
|
import sandbox.org.bouncycastle.asn1.x509.AlgorithmIdentifier
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy class that implements just enough of [net.corda.core.crypto.SignatureScheme]
|
||||||
|
* to allow us to compile [sandbox.net.corda.core.crypto.Crypto].
|
||||||
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
|
class SignatureScheme(
|
||||||
|
val schemeNumberID: Int,
|
||||||
|
val schemeCodeName: String,
|
||||||
|
val signatureOID: AlgorithmIdentifier,
|
||||||
|
val alternativeOIDs: List<AlgorithmIdentifier>,
|
||||||
|
val providerName: String,
|
||||||
|
val algorithmName: String,
|
||||||
|
val signatureName: String,
|
||||||
|
val algSpec: AlgorithmParameterSpec?,
|
||||||
|
val keySize: Integer?,
|
||||||
|
val desc: String
|
||||||
|
) : Object()
|
@ -0,0 +1,7 @@
|
|||||||
|
package sandbox.net.corda.core.crypto
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a dummy class that implements just enough of [net.corda.core.crypto.TransactionSignature]
|
||||||
|
* to allow us to compile [sandbox.net.corda.core.crypto.Crypto].
|
||||||
|
*/
|
||||||
|
class TransactionSignature : sandbox.java.lang.Object()
|
@ -0,0 +1,8 @@
|
|||||||
|
package sandbox.net.corda.core.crypto.internal
|
||||||
|
|
||||||
|
/**
|
||||||
|
* THIS FILE IS DELIBERATELY EMPTY, APART FROM A SINGLE DUMMY VALUE.
|
||||||
|
* KOTLIN WILL NOT CREATE A CLASS IF THIS FILE IS COMPLETELY EMPTY.
|
||||||
|
*/
|
||||||
|
@Suppress("unused")
|
||||||
|
private const val DUMMY_VALUE = 0
|
@ -19,8 +19,7 @@ class SandboxPublicKeySerializer(
|
|||||||
taskFactory: Function<Class<out Function<*, *>>, out Function<in Any?, out Any?>>
|
taskFactory: Function<Class<out Function<*, *>>, out Function<in Any?, out Any?>>
|
||||||
) : CustomSerializer.Implements<Any>(classLoader.toSandboxAnyClass(PublicKey::class.java)) {
|
) : CustomSerializer.Implements<Any>(classLoader.toSandboxAnyClass(PublicKey::class.java)) {
|
||||||
@Suppress("unchecked_cast")
|
@Suppress("unchecked_cast")
|
||||||
private val decoder: Function<ByteArray, out Any?>
|
private val decoder = taskFactory.apply(PublicKeyDecoder::class.java) as Function<ByteArray, out Any?>
|
||||||
= taskFactory.apply(PublicKeyDecoder::class.java) as Function<ByteArray, out Any?>
|
|
||||||
|
|
||||||
override val schemaForDocumentation: Schema = Schema(emptyList())
|
override val schemaForDocumentation: Schema = Schema(emptyList())
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import net.corda.core.serialization.CordaSerializable
|
|||||||
import net.corda.core.serialization.internal._contextSerializationEnv
|
import net.corda.core.serialization.internal._contextSerializationEnv
|
||||||
import net.corda.core.serialization.serialize
|
import net.corda.core.serialization.serialize
|
||||||
import net.corda.serialization.djvm.SandboxType.KOTLIN
|
import net.corda.serialization.djvm.SandboxType.KOTLIN
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
import org.junit.jupiter.api.Assertions.assertEquals
|
import org.junit.jupiter.api.Assertions.assertEquals
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import org.junit.jupiter.api.extension.ExtendWith
|
import org.junit.jupiter.api.extension.ExtendWith
|
||||||
@ -69,13 +70,18 @@ class DeserializePublicKeyTest : TestBase(KOTLIN) {
|
|||||||
sandbox {
|
sandbox {
|
||||||
_contextSerializationEnv.set(createSandboxSerializationEnv(classLoader))
|
_contextSerializationEnv.set(createSandboxSerializationEnv(classLoader))
|
||||||
|
|
||||||
val sandboxKey = data.deserializeFor(classLoader)
|
val sandboxData = data.deserializeFor(classLoader)
|
||||||
|
|
||||||
val taskFactory = classLoader.createRawTaskFactory()
|
val taskFactory = classLoader.createRawTaskFactory().compose(classLoader.createSandboxFunction())
|
||||||
val showPublicKey = taskFactory.compose(classLoader.createSandboxFunction()).apply(ShowPublicKey::class.java)
|
val showPublicKey = taskFactory.apply(ShowPublicKey::class.java)
|
||||||
val result = showPublicKey.apply(sandboxKey) ?: fail("Result cannot be null")
|
val result = showPublicKey.apply(sandboxData) ?: fail("Result cannot be null")
|
||||||
|
|
||||||
assertEquals(ShowPublicKey().apply(compositeData), result.toString())
|
assertEquals(ShowPublicKey().apply(compositeData), result.toString())
|
||||||
|
|
||||||
|
val sandboxKey = taskFactory.apply(GetPublicKey::class.java)
|
||||||
|
.apply(sandboxData) ?: fail("PublicKey cannot be null")
|
||||||
|
assertThat(sandboxKey::class.java.name)
|
||||||
|
.isEqualTo("sandbox." + CompositeKey::class.java.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -86,6 +92,12 @@ class DeserializePublicKeyTest : TestBase(KOTLIN) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class GetPublicKey : Function<PublicKeyData, PublicKey> {
|
||||||
|
override fun apply(data: PublicKeyData): PublicKey {
|
||||||
|
return data.key
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@CordaSerializable
|
@CordaSerializable
|
||||||
|
Loading…
Reference in New Issue
Block a user