Merge remote-tracking branch 'open/master' into shams-os-merge-040118

This commit is contained in:
Shams Asari 2018-01-04 18:32:15 +00:00
commit b577b680ff
17 changed files with 200 additions and 28 deletions

View File

@ -30,6 +30,7 @@ import org.bouncycastle.jcajce.provider.asymmetric.rsa.BCRSAPublicKey
import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter
import org.bouncycastle.jce.ECNamedCurveTable
import org.bouncycastle.jce.provider.BouncyCastleProvider
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec
import org.bouncycastle.jce.spec.ECParameterSpec
import org.bouncycastle.jce.spec.ECPrivateKeySpec
import org.bouncycastle.jce.spec.ECPublicKeySpec
@ -808,7 +809,7 @@ object Crypto {
/**
* Returns a key pair derived from the given [BigInteger] entropy. This is useful for unit tests
* and other cases where you want hard-coded private keys.
* Currently, [EDDSA_ED25519_SHA512] is the sole scheme supported for this operation.
* Currently, the following schemes are supported: [EDDSA_ED25519_SHA512], [ECDSA_SECP256R1_SHA256] and [ECDSA_SECP256K1_SHA256].
* @param signatureScheme a supported [SignatureScheme], see [Crypto].
* @param entropy a [BigInteger] value.
* @return a new [KeyPair] from an entropy input.
@ -818,6 +819,7 @@ object Crypto {
fun deriveKeyPairFromEntropy(signatureScheme: SignatureScheme, entropy: BigInteger): KeyPair {
return when (signatureScheme) {
EDDSA_ED25519_SHA512 -> deriveEdDSAKeyPairFromEntropy(entropy)
ECDSA_SECP256R1_SHA256, ECDSA_SECP256K1_SHA256 -> deriveECDSAKeyPairFromEntropy(signatureScheme, entropy)
else -> throw IllegalArgumentException("Unsupported signature scheme for fixed entropy-based key pair " +
"generation: ${signatureScheme.schemeCodeName}")
}
@ -832,6 +834,9 @@ object Crypto {
fun deriveKeyPairFromEntropy(entropy: BigInteger): KeyPair = deriveKeyPairFromEntropy(DEFAULT_SIGNATURE_SCHEME, entropy)
// Custom key pair generator from entropy.
// The BigIntenger.toByteArray() uses the two's-complement representation.
// The entropy is transformed to a byte array in big-endian byte-order and
// only the first ed25519.field.getb() / 8 bytes are used.
private fun deriveEdDSAKeyPairFromEntropy(entropy: BigInteger): KeyPair {
val params = EDDSA_ED25519_SHA512.algSpec as EdDSANamedCurveSpec
val bytes = entropy.toByteArray().copyOf(params.curve.field.getb() / 8) // Need to pad the entropy to the valid seed length.
@ -840,6 +845,32 @@ object Crypto {
return KeyPair(EdDSAPublicKey(pub), EdDSAPrivateKey(priv))
}
// Custom key pair generator from an entropy required for various tests. It is similar to deriveKeyPairECDSA,
// but the accepted range of the input entropy is more relaxed:
// 2 <= entropy < N, where N is the order of base-point G.
private fun deriveECDSAKeyPairFromEntropy(signatureScheme: SignatureScheme, entropy: BigInteger): KeyPair {
val parameterSpec = signatureScheme.algSpec as ECNamedCurveParameterSpec
// The entropy might be a negative number and/or out of range (e.g. PRNG output).
// In such cases we retry with hash(currentEntropy).
while (entropy < ECConstants.TWO || entropy >= parameterSpec.n) {
return deriveECDSAKeyPairFromEntropy(signatureScheme, BigInteger(1, entropy.toByteArray().sha256().bytes))
}
val privateKeySpec = ECPrivateKeySpec(entropy, parameterSpec)
val priv = BCECPrivateKey("EC", privateKeySpec, BouncyCastleProvider.CONFIGURATION)
val pointQ = FixedPointCombMultiplier().multiply(parameterSpec.g, entropy)
while (pointQ.isInfinity) {
// Instead of throwing an exception, we retry with hash(entropy).
return deriveECDSAKeyPairFromEntropy(signatureScheme, BigInteger(1, entropy.toByteArray().sha256().bytes))
}
val publicKeySpec = ECPublicKeySpec(pointQ, parameterSpec)
val pub = BCECPublicKey("EC", publicKeySpec, BouncyCastleProvider.CONFIGURATION)
return KeyPair(pub, priv)
}
// Compute the HMAC-SHA512 using a privateKey as the MAC_key and a seed ByteArray.
private fun deriveHMAC(privateKey: PrivateKey, seed: ByteArray): ByteArray {
// Compute hmac(privateKey, seed).

View File

@ -118,18 +118,19 @@ fun Iterable<TransactionSignature>.byKeys() = map { it.by }.toSet()
// Allow Kotlin destructuring:
// val (private, public) = keyPair
/* The [PrivateKey] of this [KeyPair] .*/
/* The [PrivateKey] of this [KeyPair]. */
operator fun KeyPair.component1(): PrivateKey = this.private
/* The [PublicKey] of this [KeyPair] .*/
/* The [PublicKey] of this [KeyPair]. */
operator fun KeyPair.component2(): PublicKey = this.public
/** A simple wrapper that will make it easier to swap out the EC algorithm we use in future. */
/** A simple wrapper that will make it easier to swap out the signature algorithm we use in future. */
fun generateKeyPair(): KeyPair = Crypto.generateKeyPair()
/**
* Returns a key pair derived from the given private key entropy. This is useful for unit tests and other cases where
* you want hard-coded private keys.
* This currently works for the default signature scheme EdDSA ed25519 only.
* @param entropy a [BigInteger] value.
* @return a deterministically generated [KeyPair] for the [Crypto.DEFAULT_SIGNATURE_SCHEME].
*/
fun entropyToKeyPair(entropy: BigInteger): KeyPair = Crypto.deriveKeyPairFromEntropy(entropy)

View File

@ -10,7 +10,17 @@ import net.corda.core.serialization.CordaSerializable
*/
@DoNotImplement
interface FlowLogicRefFactory {
/**
* Construct a FlowLogicRef. This is intended for cases where the calling code has the relevant class already
* and can provide it directly.
*/
@Deprecated("This should be avoided, and the version which takes a class name used instead to avoid requiring the class on the classpath to deserialize calling code")
fun create(flowClass: Class<out FlowLogic<*>>, vararg args: Any?): FlowLogicRef
/**
* Construct a FlowLogicRef. This is intended for cases where the calling code does not want to require the flow
* class on the classpath for all cases where the calling code is loaded.
*/
fun create(flowClassName: String, vararg args: Any?): FlowLogicRef
fun createForRPC(flowClass: Class<out FlowLogic<*>>, vararg args: Any?): FlowLogicRef
fun toFlowLogic(ref: FlowLogicRef): FlowLogic<*>
}

View File

@ -14,21 +14,22 @@ import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey
import org.bouncycastle.jce.ECNamedCurveTable
import org.bouncycastle.jce.interfaces.ECKey
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec
import org.bouncycastle.pqc.jcajce.provider.sphincs.BCSphincs256PrivateKey
import org.bouncycastle.pqc.jcajce.provider.sphincs.BCSphincs256PublicKey
import org.junit.Assert.assertNotEquals
import org.junit.Test
import java.math.BigInteger
import java.security.KeyPairGenerator
import java.util.*
import kotlin.test.*
/**
* Run tests for cryptographic algorithms
* Run tests for cryptographic algorithms.
*/
class CryptoUtilsTest {
private val testString = "Hello World"
private val testBytes = testString.toByteArray()
private val testBytes = "Hello World".toByteArray()
// key generation test
@Test
@ -781,4 +782,113 @@ class CryptoUtilsTest {
assertEquals(dpriv2, dpriv_2)
assertEquals(dpub2, dpub_2)
}
@Test
fun `EdDSA ed25519 keyPair from entropy`() {
val keyPairPositive = Crypto.deriveKeyPairFromEntropy(Crypto.EDDSA_ED25519_SHA512, BigInteger("10"))
assertEquals("DLBL3iHCp9uRReWhhCGfCsrxZZpfAm9h9GLbfN8ijqXTq", keyPairPositive.public.toStringShort())
val keyPairNegative = Crypto.deriveKeyPairFromEntropy(Crypto.EDDSA_ED25519_SHA512, BigInteger("-10"))
assertEquals("DLC5HXnYsJAFqmM9hgPj5G8whQ4TpyE9WMBssqCayLBwA2", keyPairNegative.public.toStringShort())
val keyPairZero = Crypto.deriveKeyPairFromEntropy(Crypto.EDDSA_ED25519_SHA512, BigInteger("0"))
assertEquals("DL4UVhGh4tqu1G86UVoGNaDDNCMsBtNHzE6BSZuNNJN7W2", keyPairZero.public.toStringShort())
val keyPairOne = Crypto.deriveKeyPairFromEntropy(Crypto.EDDSA_ED25519_SHA512, BigInteger("1"))
assertEquals("DL8EZUdHixovcCynKMQzrMWBnXQAcbVDHi6ArPphqwJVzq", keyPairOne.public.toStringShort())
val keyPairBiggerThan256bits = Crypto.deriveKeyPairFromEntropy(Crypto.EDDSA_ED25519_SHA512, BigInteger("2").pow(258).minus(BigInteger.TEN))
assertEquals("DLB9K1UiBrWonn481z6NzkqoWHjMBXpfDeaet3wiwRNWSU", keyPairBiggerThan256bits.public.toStringShort())
// The underlying implementation uses the first 256 bytes of the entropy. Thus, 2^258-10 and 2^258-50 and 2^514-10 have the same impact.
val keyPairBiggerThan256bitsV2 = Crypto.deriveKeyPairFromEntropy(Crypto.EDDSA_ED25519_SHA512, BigInteger("2").pow(258).minus(BigInteger("50")))
assertEquals("DLB9K1UiBrWonn481z6NzkqoWHjMBXpfDeaet3wiwRNWSU", keyPairBiggerThan256bitsV2.public.toStringShort())
val keyPairBiggerThan512bits = Crypto.deriveKeyPairFromEntropy(Crypto.EDDSA_ED25519_SHA512, BigInteger("2").pow(514).minus(BigInteger.TEN))
assertEquals("DLB9K1UiBrWonn481z6NzkqoWHjMBXpfDeaet3wiwRNWSU", keyPairBiggerThan512bits.public.toStringShort())
// Try another big number.
val keyPairBiggerThan258bits = Crypto.deriveKeyPairFromEntropy(Crypto.EDDSA_ED25519_SHA512, BigInteger("2").pow(259).plus(BigInteger.ONE))
assertEquals("DL5tEFVMXMGrzwjfCAW34JjkhsRkPfFyJ38iEnmpB6L2Z9", keyPairBiggerThan258bits.public.toStringShort())
}
@Test
fun `ECDSA R1 keyPair from entropy`() {
val keyPairPositive = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256R1_SHA256, BigInteger("10"))
assertEquals("DLHDcxuSt9J3cbjd2Dsx4rAgYYA7BAP7A8VLrFiq1tH9yy", keyPairPositive.public.toStringShort())
// The underlying implementation uses the hash of entropy if it is out of range 2 < entropy < N, where N the order of the group.
val keyPairNegative = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256R1_SHA256, BigInteger("-10"))
assertEquals("DLBASmjiMZuu1g3EtdHJxfSueXE8PRoUWbkdU61Qcnpamt", keyPairNegative.public.toStringShort())
val keyPairZero = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256R1_SHA256, BigInteger("0"))
assertEquals("DLH2FEHEnsT3MpCJt2gfyNjpqRqcBxeupK4YRPXvDsVEkb", keyPairZero.public.toStringShort())
// BigIntenger.Zero is out or range, so 1 and hash(1.toByteArray) would have the same impact.
val zeroHashed = BigInteger(1, BigInteger("0").toByteArray().sha256().bytes)
// Check oneHashed < N (order of the group), otherwise we would need an extra hash.
assertEquals(-1, zeroHashed.compareTo((Crypto.ECDSA_SECP256R1_SHA256.algSpec as ECNamedCurveParameterSpec).n))
val keyPairZeroHashed = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256R1_SHA256, zeroHashed)
assertEquals("DLH2FEHEnsT3MpCJt2gfyNjpqRqcBxeupK4YRPXvDsVEkb", keyPairZeroHashed.public.toStringShort())
val keyPairOne = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256R1_SHA256, BigInteger("1"))
assertEquals("DLHrtKwjv6onq9HcrQDJPs8Cgtai5mZU5ZU6sb1ivJjx3z", keyPairOne.public.toStringShort())
// BigIntenger.ONE is out or range, so 1 and hash(1.toByteArray) would have the same impact.
val oneHashed = BigInteger(1, BigInteger("1").toByteArray().sha256().bytes)
// Check oneHashed < N (order of the group), otherwise we would need an extra hash.
assertEquals(-1, oneHashed.compareTo((Crypto.ECDSA_SECP256R1_SHA256.algSpec as ECNamedCurveParameterSpec).n))
val keyPairOneHashed = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256R1_SHA256, oneHashed)
assertEquals("DLHrtKwjv6onq9HcrQDJPs8Cgtai5mZU5ZU6sb1ivJjx3z", keyPairOneHashed.public.toStringShort())
// 2 is in the range.
val keyPairTwo = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256R1_SHA256, BigInteger("2"))
assertEquals("DLFoz6txJ3vHcKNSM1vFxHJUoEQ69PorBwW64dHsAnEoZB", keyPairTwo.public.toStringShort())
// Try big numbers that are out of range.
val keyPairBiggerThan256bits = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256R1_SHA256, BigInteger("2").pow(258).minus(BigInteger.TEN))
assertEquals("DLBv6fZqaCTbE4L7sgjbt19biXHMgU9CzR5s8g8XBJjZ11", keyPairBiggerThan256bits.public.toStringShort())
val keyPairBiggerThan256bitsV2 = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256R1_SHA256, BigInteger("2").pow(258).minus(BigInteger("50")))
assertEquals("DLANmjhGSVdLyghxcPHrn3KuGatscf6LtvqifUDxw7SGU8", keyPairBiggerThan256bitsV2.public.toStringShort())
val keyPairBiggerThan512bits = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256R1_SHA256, BigInteger("2").pow(514).minus(BigInteger.TEN))
assertEquals("DL9sKwMExBTD3MnJN6LWGqo496Erkebs9fxZtXLVJUBY9Z", keyPairBiggerThan512bits.public.toStringShort())
val keyPairBiggerThan258bits = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256R1_SHA256, BigInteger("2").pow(259).plus(BigInteger.ONE))
assertEquals("DLBwjWwPJSF9E7b1NWaSbEJ4oK8CF7RDGWd648TiBhZoL1", keyPairBiggerThan258bits.public.toStringShort())
}
@Test
fun `ECDSA K1 keyPair from entropy`() {
val keyPairPositive = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256K1_SHA256, BigInteger("10"))
assertEquals("DL6pYKUgH17az8MLdonvvUtUPN8TqwpCGcdgLr7vg3skCU", keyPairPositive.public.toStringShort())
// The underlying implementation uses the hash of entropy if it is out of range 2 <= entropy < N, where N the order of the group.
val keyPairNegative = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256K1_SHA256, BigInteger("-10"))
assertEquals("DLnpXhxece69Nyqgm3pPt3yV7ESQYDJKoYxs1hKgfBAEu", keyPairNegative.public.toStringShort())
val keyPairZero = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256K1_SHA256, BigInteger("0"))
assertEquals("DLBC28e18T6KsYwjTFfUWJfhvHjvYVapyVf6antnqUkbgd", keyPairZero.public.toStringShort())
// BigIntenger.Zero is out or range, so 1 and hash(1.toByteArray) would have the same impact.
val zeroHashed = BigInteger(1, BigInteger("0").toByteArray().sha256().bytes)
// Check oneHashed < N (order of the group), otherwise we would need an extra hash.
assertEquals(-1, zeroHashed.compareTo((Crypto.ECDSA_SECP256K1_SHA256.algSpec as ECNamedCurveParameterSpec).n))
val keyPairZeroHashed = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256K1_SHA256, zeroHashed)
assertEquals("DLBC28e18T6KsYwjTFfUWJfhvHjvYVapyVf6antnqUkbgd", keyPairZeroHashed.public.toStringShort())
val keyPairOne = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256K1_SHA256, BigInteger("1"))
assertEquals("DLBimRXdEQhJUTpL6f9ri9woNdsze6mwkRrhsML13Eh7ET", keyPairOne.public.toStringShort())
// BigIntenger.ONE is out or range, so 1 and hash(1.toByteArray) would have the same impact.
val oneHashed = BigInteger(1, BigInteger("1").toByteArray().sha256().bytes)
// Check oneHashed < N (order of the group), otherwise we would need an extra hash.
assertEquals(-1, oneHashed.compareTo((Crypto.ECDSA_SECP256K1_SHA256.algSpec as ECNamedCurveParameterSpec).n))
val keyPairOneHashed = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256K1_SHA256, oneHashed)
assertEquals("DLBimRXdEQhJUTpL6f9ri9woNdsze6mwkRrhsML13Eh7ET", keyPairOneHashed.public.toStringShort())
// 2 is in the range.
val keyPairTwo = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256K1_SHA256, BigInteger("2"))
assertEquals("DLG32UWaevGw9YY7w1Rf9mmK88biavgpDnJA9bG4GapVPs", keyPairTwo.public.toStringShort())
// Try big numbers that are out of range.
val keyPairBiggerThan256bits = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256K1_SHA256, BigInteger("2").pow(258).minus(BigInteger.TEN))
assertEquals("DLGHsdv2xeAuM7n3sBc6mFfiphXe6VSf3YxqvviKDU6Vbd", keyPairBiggerThan256bits.public.toStringShort())
val keyPairBiggerThan256bitsV2 = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256K1_SHA256, BigInteger("2").pow(258).minus(BigInteger("50")))
assertEquals("DL9yJfiNGqteRrKPjGUkRQkeqzuQ4kwcYQWMCi5YKuUHrk", keyPairBiggerThan256bitsV2.public.toStringShort())
val keyPairBiggerThan512bits = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256K1_SHA256, BigInteger("2").pow(514).minus(BigInteger.TEN))
assertEquals("DL3Wr5EQGrMTaKBy5XMvG8rvSfKX1AYZLCRU8kixGbxt1E", keyPairBiggerThan512bits.public.toStringShort())
val keyPairBiggerThan258bits = Crypto.deriveKeyPairFromEntropy(Crypto.ECDSA_SECP256K1_SHA256, BigInteger("2").pow(259).plus(BigInteger.ONE))
assertEquals("DL7NbssqvuuJ4cqFkkaVYu9j1MsVswESGgCfbqBS9ULwuM", keyPairBiggerThan258bits.public.toStringShort())
}
}

View File

@ -29,8 +29,8 @@ import java.util.*
class CashExitFlow(private val amount: Amount<Currency>,
private val issuerRef: OpaqueBytes,
progressTracker: ProgressTracker) : AbstractCashFlow<AbstractCashFlow.Result>(progressTracker) {
constructor(amount: Amount<Currency>, issueRef: OpaqueBytes) : this(amount, issueRef, tracker())
constructor(request: ExitRequest) : this(request.amount, request.issueRef, tracker())
constructor(amount: Amount<Currency>, issuerRef: OpaqueBytes) : this(amount, issuerRef, tracker())
constructor(request: ExitRequest) : this(request.amount, request.issuerRef, tracker())
companion object {
fun tracker() = ProgressTracker(GENERATING_TX, SIGNING_TX, FINALISING_TX)
@ -78,5 +78,5 @@ class CashExitFlow(private val amount: Amount<Currency>,
}
@CordaSerializable
class ExitRequest(amount: Amount<Currency>, val issueRef: OpaqueBytes) : AbstractRequest(amount)
class ExitRequest(amount: Amount<Currency>, val issuerRef: OpaqueBytes) : AbstractRequest(amount)
}

View File

@ -6,7 +6,7 @@ Generates a text summary of Corda's public API that we can check for API-breakin
$ gradlew generateApi
```
See [here](../../docs/source/api-index.rst) for Corda's public API strategy. We will need to
See [here](../../docs/source/corda-api.rst) for Corda's public API strategy. We will need to
apply this plugin to other modules in future Corda releases as those modules' APIs stabilise.
Basically, this plugin will document a module's `public` and `protected` classes/methods/fields,

View File

@ -85,7 +85,7 @@ private fun <T : Any> propertiesForSerializationFromConstructor(kotlinConstructo
val matchingProperty = properties[name] ?:
try {
clazz.getDeclaredField(param.name)
throw NotSerializableException("Property '$name' or it's getter is non public, this renders class '$clazz' unserializable")
throw NotSerializableException("Property '$name' or its getter is non public, this renders class '$clazz' unserializable")
} catch (e: NoSuchFieldException) {
throw NotSerializableException("No property matching constructor parameter named '$name' of '$clazz'. " +
"If using Java, check that you have the -parameters option specified in the Java compiler. " +

View File

@ -10,7 +10,7 @@ public class ErrorMessageTests {
private String errMsg(String property, String testname) {
return "Property '"
+ property
+ "' or it's getter is non public, this renders class 'class "
+ "' or its getter is non public, this renders class 'class "
+ testname
+ "$C' unserializable -> class "
+ testname

View File

@ -10,7 +10,7 @@ class ErrorMessagesTests {
}
private fun errMsg(property:String, testname: String) =
"Property '$property' or it's getter is non public, this renders class 'class $testname\$C' unserializable -> class $testname\$C"
"Property '$property' or its getter is non public, this renders class 'class $testname\$C' unserializable -> class $testname\$C"
@Test
fun privateProperty() {

View File

@ -40,6 +40,18 @@ class FlowLogicRefFactoryImpl(private val classloader: ClassLoader) : SingletonS
return createForRPC(flowClass, *args)
}
override fun create(flowClassName: String, vararg args: Any?): FlowLogicRef {
val flowClass = Class.forName(flowClassName, true, classloader).asSubclass(FlowLogic::class.java)
if (flowClass == null) {
throw IllegalArgumentException("The class $flowClassName is not a subclass of FlowLogic.")
} else {
if (!flowClass.isAnnotationPresent(SchedulableFlow::class.java)) {
throw IllegalFlowLogicException(flowClass, "because it's not a schedulable flow")
}
return createForRPC(flowClass, *args)
}
}
override fun createForRPC(flowClass: Class<out FlowLogic<*>>, vararg args: Any?): FlowLogicRef {
// TODO: This is used via RPC but it's probably better if we pass in argument names and values explicitly
// to avoid requiring only a single constructor.

View File

@ -30,6 +30,7 @@ import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
import java.time.Instant
import kotlin.reflect.jvm.jvmName
import kotlin.test.assertEquals
class ScheduledFlowTests {
@ -52,7 +53,7 @@ class ScheduledFlowTests {
override val linearId: UniqueIdentifier = UniqueIdentifier()) : SchedulableState, LinearState {
override fun nextScheduledActivity(thisStateRef: StateRef, flowLogicRefFactory: FlowLogicRefFactory): ScheduledActivity? {
return if (!processed) {
val logicRef = flowLogicRefFactory.create(ScheduledFlow::class.java, thisStateRef)
val logicRef = flowLogicRefFactory.create(ScheduledFlow::class.jvmName, thisStateRef)
ScheduledActivity(logicRef, creationTime)
} else {
null

View File

@ -1,17 +1,20 @@
package net.corda.node.services.events
package net.corda.node.services.statemachine
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.IllegalFlowLogicException
import net.corda.node.services.statemachine.FlowLogicRefFactoryImpl
import net.corda.core.flows.SchedulableFlow
import org.junit.Test
import java.time.Duration
import kotlin.reflect.jvm.jvmName
import kotlin.test.assertEquals
class FlowLogicRefTest {
class FlowLogicRefFactoryImplTest {
data class ParamType1(val value: Int)
data class ParamType2(val value: String)
@Suppress("UNUSED_PARAMETER", "unused") // Things are used via reflection.
@SchedulableFlow
class KotlinFlowLogic(A: ParamType1, b: ParamType2) : FlowLogic<Unit>() {
constructor() : this(ParamType1(1), ParamType2("2"))
@ -26,6 +29,7 @@ class FlowLogicRefTest {
override fun call() = Unit
}
@SchedulableFlow
class KotlinNoArgFlowLogic : FlowLogic<Unit>() {
override fun call() = Unit
}
@ -37,18 +41,18 @@ class FlowLogicRefTest {
private val flowLogicRefFactory = FlowLogicRefFactoryImpl(FlowLogicRefFactoryImpl::class.java.classLoader)
@Test
fun `create kotlin no arg`() {
flowLogicRefFactory.createForRPC(KotlinNoArgFlowLogic::class.java)
flowLogicRefFactory.create(KotlinNoArgFlowLogic::class.jvmName)
}
@Test
fun `create kotlin`() {
fun `should create kotlin types`() {
val args = mapOf(Pair("A", ParamType1(1)), Pair("b", ParamType2("Hello Jack")))
flowLogicRefFactory.createKotlin(KotlinFlowLogic::class.java, args)
}
@Test
fun `create primary`() {
flowLogicRefFactory.createForRPC(KotlinFlowLogic::class.java, ParamType1(1), ParamType2("Hello Jack"))
flowLogicRefFactory.create(KotlinFlowLogic::class.jvmName, ParamType1(1), ParamType2("Hello Jack"))
}
@Test
@ -76,6 +80,6 @@ class FlowLogicRefTest {
@Test(expected = IllegalFlowLogicException::class)
fun `create for non-schedulable flow logic`() {
flowLogicRefFactory.create(NonSchedulableFlow::class.java)
flowLogicRefFactory.create(NonSchedulableFlow::class.jvmName)
}
}

View File

@ -24,6 +24,7 @@ import net.corda.testing.node.startFlow
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Test
import java.time.Instant
import java.util.*
@ -99,6 +100,7 @@ class NotaryServiceTests {
assertThat(ex.error).isInstanceOf(NotaryError.TimeWindowInvalid::class.java)
}
@Ignore("Only applies to deterministic signature schemes (e.g. EdDSA) and when deterministic metadata is attached (no timestamps or nonces)")
@Test
fun `should sign identical transaction multiple times (signing is idempotent)`() {
val stx = run {

View File

@ -616,7 +616,7 @@ class InterestRateSwap : Contract {
// This is perhaps not how we should determine the time point in the business day, but instead expect the schedule to detail some of these aspects
val instant = suggestInterestRateAnnouncementTimeWindow(index = nextFixingOf.name, source = floatingLeg.indexSource, date = nextFixingOf.forDay).fromTime!!
return ScheduledActivity(flowLogicRefFactory.create(FixingFlow.FixingRoleDecider::class.java, thisStateRef), instant)
return ScheduledActivity(flowLogicRefFactory.create("net.corda.irs.flows.FixingFlow\$FixingRoleDecider", thisStateRef), instant)
}
// DOCEND 1

View File

@ -7,7 +7,6 @@ import net.corda.core.identity.Party
import net.corda.core.serialization.CordaSerializable
import net.corda.core.transactions.TransactionBuilder
import net.corda.finance.contracts.DealState
import net.corda.vega.flows.SimmRevaluation
import java.time.LocalDate
import java.time.ZoneOffset
import java.time.temporal.ChronoUnit
@ -32,7 +31,7 @@ data class PortfolioState(val portfolio: List<StateRef>,
val valuer: AbstractParty get() = participants[0]
override fun nextScheduledActivity(thisStateRef: StateRef, flowLogicRefFactory: FlowLogicRefFactory): ScheduledActivity {
val flow = flowLogicRefFactory.create(SimmRevaluation.Initiator::class.java, thisStateRef, LocalDate.now())
val flow = flowLogicRefFactory.create("net.corda.vega.flows.SimmRevaluation\$Initiator", thisStateRef, LocalDate.now())
return ScheduledActivity(flow, LocalDate.now().plus(1, ChronoUnit.DAYS).atStartOfDay().toInstant(ZoneOffset.UTC))
}

View File

@ -6,6 +6,7 @@ import com.nhaarman.mockito_kotlin.doReturn
import com.nhaarman.mockito_kotlin.whenever
import net.corda.core.DoNotImplement
import net.corda.core.crypto.entropyToKeyPair
import net.corda.core.crypto.Crypto
import net.corda.core.crypto.random63BitValue
import net.corda.core.identity.CordaX500Name
import net.corda.core.identity.Party
@ -326,7 +327,8 @@ open class MockNetwork(private val cordappPackages: List<String>,
// This is not thread safe, but node construction is done on a single thread, so that should always be fine
override fun generateKeyPair(): KeyPair {
counter = counter.add(BigInteger.ONE)
return entropyToKeyPair(counter)
// The MockNode specifically uses EdDSA keys as they are fixed and stored in json files for some tests (e.g IRSSimulation).
return Crypto.deriveKeyPairFromEntropy(Crypto.EDDSA_ED25519_SHA512, counter)
}
/**

View File

@ -152,7 +152,7 @@ class ExplorerSimulation(private val options: OptionSet) {
it.startFlow(::CashIssueAndPaymentFlow, request).log(i, "${request.amount.token}Issuer")
}
is ExitRequest -> issuers[request.amount.token]?.let {
println("${Instant.now()} [$i] EXITING ${request.amount} with ref ${request.issueRef}")
println("${Instant.now()} [$i] EXITING ${request.amount} with ref ${request.issuerRef}")
it.startFlow(::CashExitFlow, request).log(i, "${request.amount.token}Exit")
}
else -> throw IllegalArgumentException("Unsupported command: $request")