Moved the majority of the contents of Utils.kt into either InternalUtils.kt or KotlinUtils.kt.

What remains is being dealt with in another PR.
This commit is contained in:
Shams Asari 2017-07-24 10:12:27 +01:00
parent 8acbd86c70
commit 407b467f67
49 changed files with 353 additions and 380 deletions

View File

@ -2,7 +2,7 @@ package net.corda.client.jfx
import net.corda.client.jfx.model.NodeMonitorModel import net.corda.client.jfx.model.NodeMonitorModel
import net.corda.client.jfx.model.ProgressTrackingEvent import net.corda.client.jfx.model.ProgressTrackingEvent
import net.corda.core.bufferUntilSubscribed import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.contracts.Amount import net.corda.core.contracts.Amount
import net.corda.core.contracts.DOLLARS import net.corda.core.contracts.DOLLARS
import net.corda.core.contracts.USD import net.corda.core.contracts.USD

View File

@ -1,7 +1,7 @@
package net.corda.client.rpc.internal package net.corda.client.rpc.internal
import net.corda.core.crypto.random63BitValue import net.corda.core.crypto.random63BitValue
import net.corda.core.logElapsedTime import net.corda.core.internal.logElapsedTime
import net.corda.core.messaging.RPCOps import net.corda.core.messaging.RPCOps
import net.corda.core.serialization.SerializationContext import net.corda.core.serialization.SerializationContext
import net.corda.core.serialization.SerializationDefaults import net.corda.core.serialization.SerializationDefaults

View File

@ -5,7 +5,7 @@ import com.google.common.hash.HashingInputStream
import net.corda.client.rpc.CordaRPCConnection import net.corda.client.rpc.CordaRPCConnection
import net.corda.client.rpc.notUsed import net.corda.client.rpc.notUsed
import net.corda.contracts.asset.Cash import net.corda.contracts.asset.Cash
import net.corda.core.InputStreamAndHash import net.corda.core.internal.InputStreamAndHash
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.getOrThrow import net.corda.core.getOrThrow

View File

@ -1,30 +0,0 @@
package net.corda.core
import java.util.*
import java.util.Spliterator.*
import java.util.stream.IntStream
import java.util.stream.Stream
import java.util.stream.StreamSupport
import kotlin.streams.asSequence
private fun IntProgression.spliteratorOfInt(): Spliterator.OfInt {
val kotlinIterator = iterator()
val javaIterator = object : PrimitiveIterator.OfInt {
override fun nextInt() = kotlinIterator.nextInt()
override fun hasNext() = kotlinIterator.hasNext()
override fun remove() = throw UnsupportedOperationException("remove")
}
val spliterator = Spliterators.spliterator(
javaIterator,
(1 + (last - first) / step).toLong(),
SUBSIZED or IMMUTABLE or NONNULL or SIZED or ORDERED or SORTED or DISTINCT
)
return if (step > 0) spliterator else object : Spliterator.OfInt by spliterator {
override fun getComparator() = Comparator.reverseOrder<Int>()
}
}
fun IntProgression.stream(): IntStream = StreamSupport.intStream(spliteratorOfInt(), false)
@Suppress("UNCHECKED_CAST") // When toArray has filled in the array, the component type is no longer T? but T (that may itself be nullable).
inline fun <reified T> Stream<out T>.toTypedArray() = toArray { size -> arrayOfNulls<T>(size) } as Array<T>

View File

@ -1,49 +1,18 @@
// TODO Move out the Kotlin specific stuff into a separate file
@file:JvmName("Utils") @file:JvmName("Utils")
package net.corda.core package net.corda.core
import com.google.common.base.Throwables
import com.google.common.io.ByteStreams
import com.google.common.util.concurrent.* import com.google.common.util.concurrent.*
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.sha256
import net.corda.core.internal.createDirectories
import net.corda.core.internal.div
import net.corda.core.internal.write
import org.slf4j.Logger import org.slf4j.Logger
import rx.Observable import rx.Observable
import rx.Observer import rx.Observer
import rx.subjects.PublishSubject
import rx.subjects.UnicastSubject
import java.io.*
import java.math.BigDecimal
import java.nio.file.Files
import java.nio.file.Path
import java.time.Duration import java.time.Duration
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
import java.util.concurrent.ExecutionException import java.util.concurrent.ExecutionException
import java.util.concurrent.Future import java.util.concurrent.Future
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import java.util.zip.Deflater
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import java.util.zip.ZipOutputStream
// TODO: Review by EOY2016 if we ever found these utilities helpful. // TODO Delete this file once the Future stuff is out of here
val Int.bd: BigDecimal get() = BigDecimal(this)
val Double.bd: BigDecimal get() = BigDecimal(this)
val String.bd: BigDecimal get() = BigDecimal(this)
val Long.bd: BigDecimal get() = BigDecimal(this)
fun String.abbreviate(maxWidth: Int): String = if (length <= maxWidth) this else take(maxWidth - 1) + ""
/** Like the + operator but throws an exception in case of integer overflow. */
infix fun Int.checkedAdd(b: Int) = Math.addExact(this, b)
/** Like the + operator but throws an exception in case of integer overflow. */
@Suppress("unused")
infix fun Long.checkedAdd(b: Long) = Math.addExact(this, b)
/** Same as [Future.get] but with a more descriptive name, and doesn't throw [ExecutionException], instead throwing its cause */ /** Same as [Future.get] but with a more descriptive name, and doesn't throw [ExecutionException], instead throwing its cause */
fun <T> Future<T>.getOrThrow(timeout: Duration? = null): T { fun <T> Future<T>.getOrThrow(timeout: Duration? = null): T {
@ -92,163 +61,6 @@ fun <A> ListenableFuture<out A>.toObservable(): Observable<A> {
} }
} }
/** Returns the index of the given item or throws [IllegalArgumentException] if not found. */
fun <T> List<T>.indexOfOrThrow(item: T): Int {
val i = indexOf(item)
require(i != -1)
return i
}
/**
* Returns the single element matching the given [predicate], or `null` if element was not found,
* or throws if more than one element was found.
*/
fun <T> Iterable<T>.noneOrSingle(predicate: (T) -> Boolean): T? {
var single: T? = null
for (element in this) {
if (predicate(element)) {
if (single == null) {
single = element
} else throw IllegalArgumentException("Collection contains more than one matching element.")
}
}
return single
}
/** Returns single element, or `null` if element was not found, or throws if more than one element was found. */
fun <T> Iterable<T>.noneOrSingle(): T? {
var single: T? = null
for (element in this) {
if (single == null) {
single = element
} else throw IllegalArgumentException("Collection contains more than one matching element.")
}
return single
}
/** Returns a random element in the list, or null if empty */
fun <T> List<T>.randomOrNull(): T? {
if (size <= 1) return firstOrNull()
val randomIndex = (Math.random() * size).toInt()
return get(randomIndex)
}
/** Returns a random element in the list matching the given predicate, or null if none found */
fun <T> List<T>.randomOrNull(predicate: (T) -> Boolean) = filter(predicate).randomOrNull()
inline fun elapsedTime(block: () -> Unit): Duration {
val start = System.nanoTime()
block()
val end = System.nanoTime()
return Duration.ofNanos(end - start)
}
// TODO: Add inline back when a new Kotlin version is released and check if the java.lang.VerifyError
// returns in the IRSSimulationTest. If not, commit the inline back.
fun <T> logElapsedTime(label: String, logger: Logger? = null, body: () -> T): T {
// Use nanoTime as it's monotonic.
val now = System.nanoTime()
try {
return body()
} finally {
val elapsed = Duration.ofNanos(System.nanoTime() - now).toMillis()
if (logger != null)
logger.info("$label took $elapsed msec")
else
println("$label took $elapsed msec")
}
}
fun <T> Logger.logElapsedTime(label: String, body: () -> T): T = logElapsedTime(label, this, body)
/**
* Given a path to a zip file, extracts it to the given directory.
*/
fun extractZipFile(zipFile: Path, toDirectory: Path) = extractZipFile(Files.newInputStream(zipFile), toDirectory)
/**
* Given a zip file input stream, extracts it to the given directory.
*/
fun extractZipFile(inputStream: InputStream, toDirectory: Path) {
val normalisedDirectory = toDirectory.normalize().createDirectories()
ZipInputStream(BufferedInputStream(inputStream)).use {
while (true) {
val e = it.nextEntry ?: break
val outPath = (normalisedDirectory / e.name).normalize()
// Security checks: we should reject a zip that contains tricksy paths that try to escape toDirectory.
check(outPath.startsWith(normalisedDirectory)) { "ZIP contained a path that resolved incorrectly: ${e.name}" }
if (e.isDirectory) {
outPath.createDirectories()
continue
}
outPath.write { out ->
ByteStreams.copy(it, out)
}
it.closeEntry()
}
}
}
/** Convert a [ByteArrayOutputStream] to [InputStreamAndHash]. */
fun ByteArrayOutputStream.getInputStreamAndHash(baos: ByteArrayOutputStream): InputStreamAndHash {
val bytes = baos.toByteArray()
return InputStreamAndHash(ByteArrayInputStream(bytes), bytes.sha256())
}
data class InputStreamAndHash(val inputStream: InputStream, val sha256: SecureHash.SHA256) {
companion object {
/**
* Get a valid InputStream from an in-memory zip as required for some tests. The zip consists of a single file
* called "z" that contains the given content byte repeated the given number of times.
* Note that a slightly bigger than numOfExpectedBytes size is expected.
*/
@Throws(IllegalArgumentException::class)
@JvmStatic
fun createInMemoryTestZip(numOfExpectedBytes: Int, content: Byte): InputStreamAndHash {
require(numOfExpectedBytes > 0)
val baos = ByteArrayOutputStream()
ZipOutputStream(baos).use { zos ->
val arraySize = 1024
val bytes = ByteArray(arraySize) { content }
val n = (numOfExpectedBytes - 1) / arraySize + 1 // same as Math.ceil(numOfExpectedBytes/arraySize).
zos.setLevel(Deflater.NO_COMPRESSION)
zos.putNextEntry(ZipEntry("z"))
for (i in 0 until n) {
zos.write(bytes, 0, arraySize)
}
zos.closeEntry()
}
return baos.getInputStreamAndHash(baos)
}
}
}
// TODO: Generic csv printing utility for clases.
val Throwable.rootCause: Throwable get() = Throwables.getRootCause(this)
/**
* Returns an Observable that buffers events until subscribed.
* @see UnicastSubject
*/
fun <T> Observable<T>.bufferUntilSubscribed(): Observable<T> {
val subject = UnicastSubject.create<T>()
val subscription = subscribe(subject)
return subject.doOnUnsubscribe { subscription.unsubscribe() }
}
/**
* Copy an [Observer] to multiple other [Observer]s.
*/
fun <T> Observer<T>.tee(vararg teeTo: Observer<T>): Observer<T> {
val subject = PublishSubject.create<T>()
subject.subscribe(this)
teeTo.forEach { subject.subscribe(it) }
return subject
}
/** /**
* Returns a [ListenableFuture] bound to the *first* item emitted by this Observable. The future will complete with a * Returns a [ListenableFuture] bound to the *first* item emitted by this Observable. The future will complete with a
* NoSuchElementException if no items are emitted or any other error thrown by the Observable. If it's cancelled then * NoSuchElementException if no items are emitted or any other error thrown by the Observable. If it's cancelled then
@ -273,15 +85,3 @@ private class ObservableToFuture<T>(observable: Observable<T>) : AbstractFuture<
override fun onCompleted() {} override fun onCompleted() {}
} }
/** Return the sum of an Iterable of [BigDecimal]s. */
fun Iterable<BigDecimal>.sum(): BigDecimal = fold(BigDecimal.ZERO) { a, b -> a + b }
fun <T> Class<T>.checkNotUnorderedHashMap() {
if (HashMap::class.java.isAssignableFrom(this) && !LinkedHashMap::class.java.isAssignableFrom(this)) {
throw NotSerializableException("Map type $this is unstable under iteration. Suggested fix: use LinkedHashMap instead.")
}
}
fun Class<*>.requireExternal(msg: String = "Internal class")
= require(!name.startsWith("net.corda.node.") && !name.contains(".internal.")) { "$msg: $name" }

View File

@ -1,5 +1,8 @@
package net.corda.core.contracts package net.corda.core.contracts
import net.corda.core.crypto.composite.CompositeKey
import net.corda.core.utilities.exactAdd
import net.corda.core.identity.Party
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import java.math.BigDecimal import java.math.BigDecimal
import java.math.RoundingMode import java.math.RoundingMode
@ -168,7 +171,7 @@ data class Amount<T : Any>(val quantity: Long, val displayTokenSize: BigDecimal,
*/ */
operator fun plus(other: Amount<T>): Amount<T> { operator fun plus(other: Amount<T>): Amount<T> {
checkToken(other) checkToken(other)
return Amount(Math.addExact(quantity, other.quantity), displayTokenSize, token) return Amount(quantity exactAdd other.quantity, displayTokenSize, token)
} }
/** /**
@ -268,9 +271,9 @@ data class SourceAndAmount<T : Any, out P : Any>(val source: P, val amount: Amou
* but in various scenarios it may be more consistent to allow positive and negative values. * but in various scenarios it may be more consistent to allow positive and negative values.
* For example it is common for a bank to code asset flows as gains and losses from its perspective i.e. always the destination. * For example it is common for a bank to code asset flows as gains and losses from its perspective i.e. always the destination.
* @param token represents the type of asset token as would be used to construct Amount<T> objects. * @param token represents the type of asset token as would be used to construct Amount<T> objects.
* @param source is the [Party], [Account], [CompositeKey], or other identifier of the token source if quantityDelta is positive, * @param source is the [Party], [CompositeKey], or other identifier of the token source if quantityDelta is positive,
* or the token sink if quantityDelta is negative. The type P should support value equality. * or the token sink if quantityDelta is negative. The type P should support value equality.
* @param destination is the [Party], [Account], [CompositeKey], or other identifier of the token sink if quantityDelta is positive, * @param destination is the [Party], [CompositeKey], or other identifier of the token sink if quantityDelta is positive,
* or the token source if quantityDelta is negative. The type P should support value equality. * or the token source if quantityDelta is negative. The type P should support value equality.
*/ */
@CordaSerializable @CordaSerializable
@ -329,7 +332,7 @@ class AmountTransfer<T : Any, P : Any>(val quantityDelta: Long,
"Only AmountTransfer between the same two parties can be aggregated/netted" "Only AmountTransfer between the same two parties can be aggregated/netted"
} }
return if (other.source == source) { return if (other.source == source) {
AmountTransfer(Math.addExact(quantityDelta, other.quantityDelta), token, source, destination) AmountTransfer(quantityDelta exactAdd other.quantityDelta, token, source, destination)
} else { } else {
AmountTransfer(Math.subtractExact(quantityDelta, other.quantityDelta), token, source, destination) AmountTransfer(Math.subtractExact(quantityDelta, other.quantityDelta), token, source, destination)
} }

View File

@ -5,6 +5,7 @@ import net.corda.core.crypto.composite.CompositeKey.NodeAndWeight
import net.corda.core.crypto.keys import net.corda.core.crypto.keys
import net.corda.core.crypto.provider.CordaObjectIdentifier import net.corda.core.crypto.provider.CordaObjectIdentifier
import net.corda.core.crypto.toStringShort import net.corda.core.crypto.toStringShort
import net.corda.core.utilities.exactAdd
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import net.corda.core.utilities.sequence import net.corda.core.utilities.sequence
import org.bouncycastle.asn1.* import org.bouncycastle.asn1.*
@ -126,7 +127,7 @@ class CompositeKey private constructor(val threshold: Int, children: List<NodeAn
var sum = 0 var sum = 0
for ((_, weight) in children) { for ((_, weight) in children) {
require(weight > 0) { "Non-positive weight: $weight detected." } require(weight > 0) { "Non-positive weight: $weight detected." }
sum = Math.addExact(sum, weight) // Add and check for integer overflow. sum = sum exactAdd weight // Add and check for integer overflow.
} }
return sum return sum
} }

View File

@ -1,10 +1,10 @@
package net.corda.core.flows package net.corda.core.flows
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import net.corda.core.abbreviate
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.internal.FlowStateMachine import net.corda.core.internal.FlowStateMachine
import net.corda.core.internal.abbreviate
import net.corda.core.messaging.DataFeed import net.corda.core.messaging.DataFeed
import net.corda.core.node.ServiceHub import net.corda.core.node.ServiceHub
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction

View File

@ -1,7 +1,7 @@
package net.corda.core.flows package net.corda.core.flows
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import net.corda.core.checkedAdd import net.corda.core.utilities.exactAdd
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.getOrThrow import net.corda.core.getOrThrow
import net.corda.core.identity.Party import net.corda.core.identity.Party
@ -176,7 +176,7 @@ class ResolveTransactionsFlow(private val txHashes: Set<SecureHash>,
val inputHashes = downloads.flatMap { it.tx.inputs }.map { it.txhash } val inputHashes = downloads.flatMap { it.tx.inputs }.map { it.txhash }
nextRequests.addAll(inputHashes) nextRequests.addAll(inputHashes)
limitCounter = limitCounter checkedAdd nextRequests.size limitCounter = limitCounter exactAdd nextRequests.size
if (limitCounter > limit) if (limitCounter > limit)
throw ExcessivelyLargeTransactionGraph() throw ExcessivelyLargeTransactionGraph()
} }

View File

@ -1,17 +1,37 @@
package net.corda.core.internal package net.corda.core.internal
import com.google.common.base.Throwables
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.sha256
import org.slf4j.Logger
import rx.Observable
import rx.Observer
import rx.subjects.PublishSubject
import rx.subjects.UnicastSubject
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.InputStream import java.io.InputStream
import java.io.OutputStream import java.io.OutputStream
import java.lang.reflect.Field import java.lang.reflect.Field
import java.math.BigDecimal
import java.nio.charset.Charset import java.nio.charset.Charset
import java.nio.charset.StandardCharsets.UTF_8 import java.nio.charset.StandardCharsets.UTF_8
import java.nio.file.* import java.nio.file.*
import java.nio.file.attribute.FileAttribute import java.nio.file.attribute.FileAttribute
import java.time.Duration import java.time.Duration
import java.time.temporal.Temporal import java.time.temporal.Temporal
import java.util.*
import java.util.Spliterator.*
import java.util.stream.IntStream
import java.util.stream.Stream import java.util.stream.Stream
import java.util.stream.StreamSupport
import java.util.zip.Deflater
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
import kotlin.reflect.KClass import kotlin.reflect.KClass
inline val Throwable.rootCause: Throwable get() = Throwables.getRootCause(this)
infix fun Temporal.until(endExclusive: Temporal): Duration = Duration.between(this, endExclusive) infix fun Temporal.until(endExclusive: Temporal): Duration = Duration.between(this, endExclusive)
operator fun Duration.div(divider: Long): Duration = dividedBy(divider) operator fun Duration.div(divider: Long): Duration = dividedBy(divider)
@ -24,6 +44,50 @@ operator fun Duration.times(multiplicand: Long): Duration = multipliedBy(multipl
operator fun Path.div(other: String): Path = resolve(other) operator fun Path.div(other: String): Path = resolve(other)
operator fun String.div(other: String): Path = Paths.get(this) / other operator fun String.div(other: String): Path = Paths.get(this) / other
/**
* Returns the single element matching the given [predicate], or `null` if the collection is empty, or throws exception
* if more than one element was found.
*/
inline fun <T> Iterable<T>.noneOrSingle(predicate: (T) -> Boolean): T? {
val iterator = iterator()
for (single in iterator) {
if (predicate(single)) {
while (iterator.hasNext()) {
if (predicate(iterator.next())) throw IllegalArgumentException("Collection contains more than one matching element.")
}
return single
}
}
return null
}
/**
* Returns the single element, or `null` if the list is empty, or throws an exception if it has more than one element.
*/
fun <T> List<T>.noneOrSingle(): T? {
return when (size) {
0 -> null
1 -> this[0]
else -> throw IllegalArgumentException("List has more than one element.")
}
}
/** Returns a random element in the list, or `null` if empty */
fun <T> List<T>.randomOrNull(): T? {
return when (size) {
0 -> null
1 -> this[0]
else -> this[(Math.random() * size).toInt()]
}
}
/** Returns the index of the given item or throws [IllegalArgumentException] if not found. */
fun <T> List<T>.indexOfOrThrow(item: T): Int {
val i = indexOf(item)
require(i != -1)
return i
}
fun Path.createDirectory(vararg attrs: FileAttribute<*>): Path = Files.createDirectory(this, *attrs) fun Path.createDirectory(vararg attrs: FileAttribute<*>): Path = Files.createDirectory(this, *attrs)
fun Path.createDirectories(vararg attrs: FileAttribute<*>): Path = Files.createDirectories(this, *attrs) fun Path.createDirectories(vararg attrs: FileAttribute<*>): Path = Files.createDirectories(this, *attrs)
fun Path.exists(vararg options: LinkOption): Boolean = Files.exists(this, *options) fun Path.exists(vararg options: LinkOption): Boolean = Files.exists(this, *options)
@ -54,6 +118,112 @@ fun Path.writeLines(lines: Iterable<CharSequence>, charset: Charset = UTF_8, var
fun InputStream.copyTo(target: Path, vararg options: CopyOption): Long = Files.copy(this, target, *options) fun InputStream.copyTo(target: Path, vararg options: CopyOption): Long = Files.copy(this, target, *options)
fun String.abbreviate(maxWidth: Int): String = if (length <= maxWidth) this else take(maxWidth - 1) + ""
/** Return the sum of an Iterable of [BigDecimal]s. */
fun Iterable<BigDecimal>.sum(): BigDecimal = fold(BigDecimal.ZERO) { a, b -> a + b }
/**
* Returns an Observable that buffers events until subscribed.
* @see UnicastSubject
*/
fun <T> Observable<T>.bufferUntilSubscribed(): Observable<T> {
val subject = UnicastSubject.create<T>()
val subscription = subscribe(subject)
return subject.doOnUnsubscribe { subscription.unsubscribe() }
}
/** Copy an [Observer] to multiple other [Observer]s. */
fun <T> Observer<T>.tee(vararg teeTo: Observer<T>): Observer<T> {
val subject = PublishSubject.create<T>()
subject.subscribe(this)
teeTo.forEach { subject.subscribe(it) }
return subject
}
/** Executes the given code block and returns a [Duration] of how long it took to execute in nanosecond precision. */
inline fun elapsedTime(block: () -> Unit): Duration {
val start = System.nanoTime()
block()
val end = System.nanoTime()
return Duration.ofNanos(end - start)
}
fun <T> Logger.logElapsedTime(label: String, body: () -> T): T = logElapsedTime(label, this, body)
// TODO: Add inline back when a new Kotlin version is released and check if the java.lang.VerifyError
// returns in the IRSSimulationTest. If not, commit the inline back.
fun <T> logElapsedTime(label: String, logger: Logger? = null, body: () -> T): T {
// Use nanoTime as it's monotonic.
val now = System.nanoTime()
try {
return body()
} finally {
val elapsed = Duration.ofNanos(System.nanoTime() - now).toMillis()
if (logger != null)
logger.info("$label took $elapsed msec")
else
println("$label took $elapsed msec")
}
}
/** Convert a [ByteArrayOutputStream] to [InputStreamAndHash]. */
fun ByteArrayOutputStream.toInputStreamAndHash(): InputStreamAndHash {
val bytes = toByteArray()
return InputStreamAndHash(ByteArrayInputStream(bytes), bytes.sha256())
}
data class InputStreamAndHash(val inputStream: InputStream, val sha256: SecureHash.SHA256) {
companion object {
/**
* Get a valid InputStream from an in-memory zip as required for some tests. The zip consists of a single file
* called "z" that contains the given content byte repeated the given number of times.
* Note that a slightly bigger than numOfExpectedBytes size is expected.
*/
fun createInMemoryTestZip(numOfExpectedBytes: Int, content: Byte): InputStreamAndHash {
require(numOfExpectedBytes > 0)
val baos = ByteArrayOutputStream()
ZipOutputStream(baos).use { zos ->
val arraySize = 1024
val bytes = ByteArray(arraySize) { content }
val n = (numOfExpectedBytes - 1) / arraySize + 1 // same as Math.ceil(numOfExpectedBytes/arraySize).
zos.setLevel(Deflater.NO_COMPRESSION)
zos.putNextEntry(ZipEntry("z"))
for (i in 0 until n) {
zos.write(bytes, 0, arraySize)
}
zos.closeEntry()
}
return baos.toInputStreamAndHash()
}
}
}
fun IntIterator.toJavaIterator(): PrimitiveIterator.OfInt {
return object : PrimitiveIterator.OfInt {
override fun nextInt() = this@toJavaIterator.nextInt()
override fun hasNext() = this@toJavaIterator.hasNext()
override fun remove() = throw UnsupportedOperationException("remove")
}
}
private fun IntProgression.toSpliterator(): Spliterator.OfInt {
val spliterator = Spliterators.spliterator(
iterator().toJavaIterator(),
(1 + (last - first) / step).toLong(),
SUBSIZED or IMMUTABLE or NONNULL or SIZED or ORDERED or SORTED or DISTINCT
)
return if (step > 0) spliterator else object : Spliterator.OfInt by spliterator {
override fun getComparator() = Comparator.reverseOrder<Int>()
}
}
fun IntProgression.stream(parallel: Boolean = false): IntStream = StreamSupport.intStream(toSpliterator(), parallel)
@Suppress("UNCHECKED_CAST") // When toArray has filled in the array, the component type is no longer T? but T (that may itself be nullable).
inline fun <reified T> Stream<out T>.toTypedArray() = toArray { size -> arrayOfNulls<T>(size) } as Array<T>
fun <T> Class<T>.castIfPossible(obj: Any): T? = if (isInstance(obj)) cast(obj) else null fun <T> Class<T>.castIfPossible(obj: Any): T? = if (isInstance(obj)) cast(obj) else null
/** Returns a [DeclaredField] wrapper around the declared (possibly non-public) static field of the receiver [Class]. */ /** Returns a [DeclaredField] wrapper around the declared (possibly non-public) static field of the receiver [Class]. */

View File

@ -6,8 +6,7 @@ import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.messaging.DataFeed import net.corda.core.messaging.DataFeed
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
import net.corda.core.node.ServiceHub import net.corda.core.internal.randomOrNull
import net.corda.core.randomOrNull
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable
import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.asn1.x500.X500Name
import rx.Observable import rx.Observable
@ -98,9 +97,9 @@ interface NetworkMapCache {
/** Gets a notary identity by the given name. */ /** Gets a notary identity by the given name. */
fun getNotary(principal: X500Name): Party? { fun getNotary(principal: X500Name): Party? {
val notaryNode = notaryNodes.randomOrNull { val notaryNode = notaryNodes.filter {
it.advertisedServices.any { it.info.type.isSubTypeOf(ServiceType.notary) && it.info.name == principal } it.advertisedServices.any { it.info.type.isSubTypeOf(ServiceType.notary) && it.info.name == principal }
} }.randomOrNull()
return notaryNode?.notaryIdentity return notaryNode?.notaryIdentity
} }

View File

@ -1,6 +1,5 @@
package net.corda.core.serialization.amqp package net.corda.core.serialization.amqp
import net.corda.core.checkNotUnorderedHashMap
import org.apache.qpid.proton.codec.Data import org.apache.qpid.proton.codec.Data
import java.io.NotSerializableException import java.io.NotSerializableException
import java.lang.reflect.ParameterizedType import java.lang.reflect.ParameterizedType
@ -47,9 +46,9 @@ class MapSerializer(val declaredType: ParameterizedType, factory: SerializerFact
// Write map // Write map
data.putMap() data.putMap()
data.enter() data.enter()
for (entry in obj as Map<*, *>) { for ((key, value) in obj as Map<*, *>) {
output.writeObjectOrNull(entry.key, data, declaredType.actualTypeArguments[0]) output.writeObjectOrNull(key, data, declaredType.actualTypeArguments[0])
output.writeObjectOrNull(entry.value, data, declaredType.actualTypeArguments[1]) output.writeObjectOrNull(value, data, declaredType.actualTypeArguments[1])
} }
data.exit() // exit map data.exit() // exit map
} }
@ -65,3 +64,9 @@ class MapSerializer(val declaredType: ParameterizedType, factory: SerializerFact
input.readObjectOrNull(entry.key, schema, declaredType.actualTypeArguments[0]) to input.readObjectOrNull(entry.key, schema, declaredType.actualTypeArguments[0]) to
input.readObjectOrNull(entry.value, schema, declaredType.actualTypeArguments[1]) input.readObjectOrNull(entry.value, schema, declaredType.actualTypeArguments[1])
} }
internal fun Class<*>.checkNotUnorderedHashMap() {
if (HashMap::class.java.isAssignableFrom(this) && !LinkedHashMap::class.java.isAssignableFrom(this)) {
throw IllegalArgumentException("Map type $this is unstable under iteration. Suggested fix: use java.util.LinkedHashMap instead.")
}
}

View File

@ -2,7 +2,6 @@ package net.corda.core.serialization.amqp
import com.google.common.primitives.Primitives import com.google.common.primitives.Primitives
import com.google.common.reflect.TypeResolver import com.google.common.reflect.TypeResolver
import net.corda.core.checkNotUnorderedHashMap
import net.corda.core.serialization.AllWhitelist import net.corda.core.serialization.AllWhitelist
import net.corda.core.serialization.ClassWhitelist import net.corda.core.serialization.ClassWhitelist
import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.CordaSerializable

View File

@ -2,7 +2,7 @@ package net.corda.core.transactions
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.indexOfOrThrow import net.corda.core.internal.indexOfOrThrow
import net.corda.core.internal.castIfPossible import net.corda.core.internal.castIfPossible
import java.security.PublicKey import java.security.PublicKey
import java.util.* import java.util.*

View File

@ -8,10 +8,17 @@ import kotlin.reflect.KProperty
// //
// READ ME FIRST: // READ ME FIRST:
// This is a collection of public utilities useful only for Kotlin code. If you're looking to add a public utility that // This is a collection of public utilities useful only for Kotlin code. Think carefully before adding anything here and
// is also relevant to Java then put it in Utils.kt. // make sure it's tested and documented. If you're looking to add a public utility that is also relevant to Java then
// don't put it here but in a seperate file called Utils.kt
// //
/** Like the + operator but throws [ArithmeticException] in case of integer overflow. */
infix fun Int.exactAdd(b: Int): Int = Math.addExact(this, b)
/** Like the + operator but throws [ArithmeticException] in case of integer overflow. */
infix fun Long.exactAdd(b: Long): Long = Math.addExact(this, b)
/** /**
* Get the [Logger] for a class using the syntax * Get the [Logger] for a class using the syntax
* *

View File

@ -1,40 +0,0 @@
package net.corda.core
import org.junit.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
class CollectionExtensionTests {
@Test
fun `noneOrSingle returns a single item`() {
val collection = listOf(1)
assertEquals(collection.noneOrSingle(), 1)
assertEquals(collection.noneOrSingle { it == 1 }, 1)
}
@Test
fun `noneOrSingle returns null if item not found`() {
val collection = emptyList<Int>()
assertEquals(collection.noneOrSingle(), null)
}
@Test
fun `noneOrSingle throws if more than one item found`() {
val collection = listOf(1, 2)
assertFailsWith<IllegalArgumentException> { collection.noneOrSingle() }
assertFailsWith<IllegalArgumentException> { collection.noneOrSingle { it > 0 } }
}
@Test
fun `indexOfOrThrow returns index of the given item`() {
val collection = listOf(1, 2)
assertEquals(collection.indexOfOrThrow(1), 0)
assertEquals(collection.indexOfOrThrow(2), 1)
}
@Test
fun `indexOfOrThrow throws if the given item is not found`() {
val collection = listOf(1)
assertFailsWith<IllegalArgumentException> { collection.indexOfOrThrow(2) }
}
}

View File

@ -1,42 +0,0 @@
package net.corda.core
import org.junit.Assert.assertArrayEquals
import org.junit.Test
import java.util.stream.IntStream
import java.util.stream.Stream
import kotlin.test.assertEquals
class StreamsTest {
@Test
fun `IntProgression stream works`() {
assertArrayEquals(intArrayOf(1, 2, 3, 4), (1..4).stream().toArray())
assertArrayEquals(intArrayOf(1, 2, 3, 4), (1 until 5).stream().toArray())
assertArrayEquals(intArrayOf(1, 3), (1..4 step 2).stream().toArray())
assertArrayEquals(intArrayOf(1, 3), (1..3 step 2).stream().toArray())
assertArrayEquals(intArrayOf(), (1..0).stream().toArray())
assertArrayEquals(intArrayOf(1, 0), (1 downTo 0).stream().toArray())
assertArrayEquals(intArrayOf(3, 1), (3 downTo 0 step 2).stream().toArray())
assertArrayEquals(intArrayOf(3, 1), (3 downTo 1 step 2).stream().toArray())
}
@Test
fun `IntProgression spliterator characteristics and comparator`() {
val rangeCharacteristics = IntStream.range(0, 2).spliterator().characteristics()
val forward = (0..9 step 3).stream().spliterator()
assertEquals(rangeCharacteristics, forward.characteristics())
assertEquals(null, forward.comparator)
val reverse = (9 downTo 0 step 3).stream().spliterator()
assertEquals(rangeCharacteristics, reverse.characteristics())
assertEquals(Comparator.reverseOrder(), reverse.comparator)
}
@Test
fun `Stream toTypedArray works`() {
val a: Array<String> = Stream.of("one", "two").toTypedArray()
assertEquals(Array<String>::class.java, a.javaClass)
assertArrayEquals(arrayOf("one", "two"), a)
val b: Array<String?> = Stream.of("one", "two", null).toTypedArray()
assertEquals(Array<String?>::class.java, b.javaClass)
assertArrayEquals(arrayOf("one", "two", null), b)
}
}

View File

@ -1,6 +1,6 @@
package net.corda.core.crypto package net.corda.core.crypto
import net.corda.core.toTypedArray import net.corda.core.internal.toTypedArray
import net.corda.node.utilities.KEYSTORE_TYPE import net.corda.node.utilities.KEYSTORE_TYPE
import net.corda.node.utilities.addOrReplaceCertificate import net.corda.node.utilities.addOrReplaceCertificate
import net.corda.node.utilities.addOrReplaceKey import net.corda.node.utilities.addOrReplaceKey

View File

@ -5,7 +5,7 @@ import net.corda.core.crypto.Crypto.generateKeyPair
import net.corda.core.crypto.X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME import net.corda.core.crypto.X509Utilities.DEFAULT_TLS_SIGNATURE_SCHEME
import net.corda.core.crypto.X509Utilities.createSelfSignedCACertificate import net.corda.core.crypto.X509Utilities.createSelfSignedCACertificate
import net.corda.core.internal.div import net.corda.core.internal.div
import net.corda.core.toTypedArray import net.corda.core.internal.toTypedArray
import net.corda.node.services.config.createKeystoreForCordaNode import net.corda.node.services.config.createKeystoreForCordaNode
import net.corda.node.utilities.* import net.corda.node.utilities.*
import net.corda.testing.MEGA_CORP import net.corda.testing.MEGA_CORP

View File

@ -0,0 +1,90 @@
package net.corda.core.internal
import org.assertj.core.api.Assertions
import org.junit.Assert.assertArrayEquals
import org.junit.Test
import java.util.stream.IntStream
import java.util.stream.Stream
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith
class InternalUtilsTest {
@Test
fun `noneOrSingle on an empty collection`() {
val collection = emptyList<Int>()
Assertions.assertThat(collection.noneOrSingle()).isNull()
Assertions.assertThat(collection.noneOrSingle { it == 1 }).isNull()
}
@Test
fun `noneOrSingle on a singleton collection`() {
val collection = listOf(1)
Assertions.assertThat(collection.noneOrSingle()).isEqualTo(1)
Assertions.assertThat(collection.noneOrSingle { it == 1 }).isEqualTo(1)
Assertions.assertThat(collection.noneOrSingle { it == 2 }).isNull()
}
@Test
fun `noneOrSingle on a collection with two items`() {
val collection = listOf(1, 2)
assertFailsWith<IllegalArgumentException> { collection.noneOrSingle() }
Assertions.assertThat(collection.noneOrSingle { it == 1 }).isEqualTo(1)
Assertions.assertThat(collection.noneOrSingle { it == 2 }).isEqualTo(2)
Assertions.assertThat(collection.noneOrSingle { it == 3 }).isNull()
assertFailsWith<IllegalArgumentException> { collection.noneOrSingle { it > 0 } }
}
@Test
fun `noneOrSingle on a collection with items 1, 2, 1`() {
val collection = listOf(1, 2, 1)
assertFailsWith<IllegalArgumentException> { collection.noneOrSingle() }
assertFailsWith<IllegalArgumentException> { collection.noneOrSingle { it == 1 } }
Assertions.assertThat(collection.noneOrSingle { it == 2 }).isEqualTo(2)
}
@Test
fun `indexOfOrThrow returns index of the given item`() {
val collection = listOf(1, 2)
assertEquals(collection.indexOfOrThrow(1), 0)
assertEquals(collection.indexOfOrThrow(2), 1)
}
@Test
fun `indexOfOrThrow throws if the given item is not found`() {
val collection = listOf(1)
assertFailsWith<IllegalArgumentException> { collection.indexOfOrThrow(2) }
}
@Test
fun `IntProgression stream works`() {
assertArrayEquals(intArrayOf(1, 2, 3, 4), (1..4).stream().toArray())
assertArrayEquals(intArrayOf(1, 2, 3, 4), (1 until 5).stream().toArray())
assertArrayEquals(intArrayOf(1, 3), (1..4 step 2).stream().toArray())
assertArrayEquals(intArrayOf(1, 3), (1..3 step 2).stream().toArray())
assertArrayEquals(intArrayOf(), (1..0).stream().toArray())
assertArrayEquals(intArrayOf(1, 0), (1 downTo 0).stream().toArray())
assertArrayEquals(intArrayOf(3, 1), (3 downTo 0 step 2).stream().toArray())
assertArrayEquals(intArrayOf(3, 1), (3 downTo 1 step 2).stream().toArray())
}
@Test
fun `IntProgression spliterator characteristics and comparator`() {
val rangeCharacteristics = IntStream.range(0, 2).spliterator().characteristics()
val forward = (0..9 step 3).stream().spliterator()
assertEquals(rangeCharacteristics, forward.characteristics())
assertEquals(null, forward.comparator)
val reverse = (9 downTo 0 step 3).stream().spliterator()
assertEquals(rangeCharacteristics, reverse.characteristics())
assertEquals(Comparator.reverseOrder(), reverse.comparator)
}
@Test
fun `Stream toTypedArray works`() {
val a: Array<String> = Stream.of("one", "two").toTypedArray()
assertEquals(Array<String>::class.java, a.javaClass)
assertArrayEquals(arrayOf("one", "two"), a)
val b: Array<String?> = Stream.of("one", "two", null).toTypedArray()
assertEquals(Array<String?>::class.java, b.javaClass)
assertArrayEquals(arrayOf("one", "two", null), b)
}
}

View File

@ -240,7 +240,7 @@ class SerializationOutputTests {
serdes(obj) serdes(obj)
} }
@Test(expected = NotSerializableException::class) @Test(expected = IllegalArgumentException::class)
fun `test dislike of HashMap`() { fun `test dislike of HashMap`() {
val obj = WrapHashMap(HashMap<String, String>()) val obj = WrapHashMap(HashMap<String, String>())
serdes(obj) serdes(obj)

View File

@ -12,3 +12,12 @@ This section describes the APIs that are available for the development of CorDap
* :doc:`api-core-types` * :doc:`api-core-types`
Before reading this page, you should be familiar with the :doc:`key concepts of Corda <key-concepts>`. Before reading this page, you should be familiar with the :doc:`key concepts of Corda <key-concepts>`.
Internal
--------
Code that falls into the following package namespaces are for internal use only and not public. In a future release the
node will not load any CorDapp which uses them.
* Any package in the ``net.corda`` namespace which contains ``.internal``
* ``net.corda.node``

View File

@ -47,6 +47,9 @@ UNRELEASED
* Added various query methods to ``LedgerTransaction`` to simplify querying of states and commands. In the same vain * Added various query methods to ``LedgerTransaction`` to simplify querying of states and commands. In the same vain
``Command`` is now parameterised on the ``CommandData`` field. ``Command`` is now parameterised on the ``CommandData`` field.
* Kotlin utilities that we deemed useful enough to keep public have been moved out of ``net.corda.core.Utils`` and into
``net.corda.core.utilities.KotlinUtils``. The other utilities have been marked as internal.
Milestone 13 Milestone 13
------------ ------------

View File

@ -5,11 +5,10 @@ package net.corda.nodeapi
import com.esotericsoftware.kryo.Registration import com.esotericsoftware.kryo.Registration
import com.esotericsoftware.kryo.Serializer import com.esotericsoftware.kryo.Serializer
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import net.corda.core.requireExternal import net.corda.core.CordaRuntimeException
import net.corda.core.serialization.* import net.corda.core.serialization.*
import net.corda.core.toFuture import net.corda.core.toFuture
import net.corda.core.toObservable import net.corda.core.toObservable
import net.corda.core.CordaRuntimeException
import net.corda.nodeapi.config.OldConfig import net.corda.nodeapi.config.OldConfig
import rx.Observable import rx.Observable
import java.io.InputStream import java.io.InputStream
@ -73,4 +72,8 @@ class RPCKryo(observableSerializer: Serializer<Observable<Any>>, whitelist: Clas
type.requireExternal("RPC not allowed to deserialise internal classes") type.requireExternal("RPC not allowed to deserialise internal classes")
return super.getRegistration(type) return super.getRegistration(type)
} }
private fun Class<*>.requireExternal(msg: String) {
require(!name.startsWith("net.corda.node.") && !name.contains(".internal.")) { "$msg: $name" }
}
} }

View File

@ -2,7 +2,7 @@ package net.corda.nodeapi.config
import com.typesafe.config.Config import com.typesafe.config.Config
import com.typesafe.config.ConfigUtil import com.typesafe.config.ConfigUtil
import net.corda.core.noneOrSingle import net.corda.core.internal.noneOrSingle
import net.corda.core.utilities.validateX500Name import net.corda.core.utilities.validateX500Name
import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.parseNetworkHostAndPort import net.corda.core.utilities.parseNetworkHostAndPort

View File

@ -1,6 +1,6 @@
package net.corda.node.services package net.corda.node.services
import net.corda.core.bufferUntilSubscribed import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.contracts.Amount import net.corda.core.contracts.Amount
import net.corda.core.contracts.POUNDS import net.corda.core.contracts.POUNDS
import net.corda.core.identity.Party import net.corda.core.identity.Party

View File

@ -1,7 +1,7 @@
package net.corda.node.services.statemachine package net.corda.node.services.statemachine
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import net.corda.core.InputStreamAndHash import net.corda.core.internal.InputStreamAndHash
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.flows.* import net.corda.core.flows.*
import net.corda.core.identity.Party import net.corda.core.identity.Party

View File

@ -3,8 +3,8 @@ package net.corda.services.messaging
import com.google.common.util.concurrent.Futures import com.google.common.util.concurrent.Futures
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import net.corda.core.crypto.random63BitValue import net.corda.core.crypto.random63BitValue
import net.corda.core.elapsedTime
import net.corda.core.getOrThrow import net.corda.core.getOrThrow
import net.corda.core.internal.elapsedTime
import net.corda.core.internal.times import net.corda.core.internal.times
import net.corda.core.messaging.MessageRecipients import net.corda.core.messaging.MessageRecipients
import net.corda.core.messaging.SingleMessageRecipient import net.corda.core.messaging.SingleMessageRecipient

View File

@ -6,11 +6,9 @@ import joptsimple.OptionException
import net.corda.core.* import net.corda.core.*
import net.corda.core.crypto.commonName import net.corda.core.crypto.commonName
import net.corda.core.crypto.orgName import net.corda.core.crypto.orgName
import net.corda.core.internal.createDirectories import net.corda.core.internal.*
import net.corda.core.internal.div
import net.corda.node.VersionInfo import net.corda.node.VersionInfo
import net.corda.core.node.services.ServiceInfo import net.corda.core.node.services.ServiceInfo
import net.corda.core.internal.Emoji
import net.corda.core.utilities.loggerFor import net.corda.core.utilities.loggerFor
import net.corda.node.ArgsParser import net.corda.node.ArgsParser
import net.corda.node.CmdLineOptions import net.corda.node.CmdLineOptions

View File

@ -9,6 +9,7 @@ import net.corda.core.crypto.X509Utilities.CORDA_CLIENT_TLS
import net.corda.core.crypto.X509Utilities.CORDA_ROOT_CA import net.corda.core.crypto.X509Utilities.CORDA_ROOT_CA
import net.corda.core.internal.ThreadBox import net.corda.core.internal.ThreadBox
import net.corda.core.internal.div import net.corda.core.internal.div
import net.corda.core.internal.noneOrSingle
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
import net.corda.core.node.services.NetworkMapCache import net.corda.core.node.services.NetworkMapCache
import net.corda.core.node.services.NetworkMapCache.MapChange import net.corda.core.node.services.NetworkMapCache.MapChange

View File

@ -3,7 +3,7 @@ package net.corda.node.services.network
import com.google.common.annotations.VisibleForTesting import com.google.common.annotations.VisibleForTesting
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import com.google.common.util.concurrent.SettableFuture import com.google.common.util.concurrent.SettableFuture
import net.corda.core.bufferUntilSubscribed import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.map import net.corda.core.map

View File

@ -1,7 +1,7 @@
package net.corda.node.services.persistence package net.corda.node.services.persistence
import net.corda.core.internal.ThreadBox import net.corda.core.internal.ThreadBox
import net.corda.core.bufferUntilSubscribed import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.flows.StateMachineRunId import net.corda.core.flows.StateMachineRunId
import net.corda.core.messaging.DataFeed import net.corda.core.messaging.DataFeed

View File

@ -1,7 +1,7 @@
package net.corda.node.services.persistence package net.corda.node.services.persistence
import com.google.common.annotations.VisibleForTesting import com.google.common.annotations.VisibleForTesting
import net.corda.core.bufferUntilSubscribed import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.messaging.DataFeed import net.corda.core.messaging.DataFeed
import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.serialization.SingletonSerializeAsToken

View File

@ -1,7 +1,7 @@
package net.corda.node.services.persistence package net.corda.node.services.persistence
import net.corda.core.internal.ThreadBox import net.corda.core.internal.ThreadBox
import net.corda.core.bufferUntilSubscribed import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.flows.StateMachineRunId import net.corda.core.flows.StateMachineRunId
import net.corda.core.messaging.DataFeed import net.corda.core.messaging.DataFeed

View File

@ -6,12 +6,12 @@ import co.paralleluniverse.fibers.Suspendable
import co.paralleluniverse.strands.Strand import co.paralleluniverse.strands.Strand
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import com.google.common.util.concurrent.SettableFuture import com.google.common.util.concurrent.SettableFuture
import net.corda.core.abbreviate
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.random63BitValue import net.corda.core.crypto.random63BitValue
import net.corda.core.flows.* import net.corda.core.flows.*
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.internal.FlowStateMachine import net.corda.core.internal.FlowStateMachine
import net.corda.core.internal.abbreviate
import net.corda.core.internal.staticField import net.corda.core.internal.staticField
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.* import net.corda.core.utilities.*
@ -122,7 +122,7 @@ class FlowStateMachineImpl<R>(override val id: StateMachineRunId,
actionOnEnd(Try.Success(result), false) actionOnEnd(Try.Success(result), false)
_resultFuture?.set(result) _resultFuture?.set(result)
logic.progressTracker?.currentStep = ProgressTracker.DONE logic.progressTracker?.currentStep = ProgressTracker.DONE
logger.debug { "Flow finished with result $result" } logger.debug { "Flow finished with result ${result.toString().abbreviate(300)}" }
} }
private fun createTransaction() { private fun createTransaction() {

View File

@ -9,7 +9,7 @@ import com.google.common.collect.HashMultimap
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import com.google.common.util.concurrent.MoreExecutors import com.google.common.util.concurrent.MoreExecutors
import net.corda.core.internal.ThreadBox import net.corda.core.internal.ThreadBox
import net.corda.core.bufferUntilSubscribed import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.random63BitValue import net.corda.core.crypto.random63BitValue
import net.corda.core.flows.FlowException import net.corda.core.flows.FlowException

View File

@ -27,7 +27,7 @@ import net.corda.core.serialization.CordaSerializable
import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.serialization.deserialize import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize import net.corda.core.serialization.serialize
import net.corda.core.toTypedArray import net.corda.core.internal.toTypedArray
import net.corda.core.transactions.FilteredTransaction import net.corda.core.transactions.FilteredTransaction
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.debug import net.corda.core.utilities.debug

View File

@ -1,7 +1,7 @@
package net.corda.node.services.vault package net.corda.node.services.vault
import net.corda.core.internal.ThreadBox import net.corda.core.internal.ThreadBox
import net.corda.core.bufferUntilSubscribed import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.contracts.ContractState import net.corda.core.contracts.ContractState
import net.corda.core.contracts.StateAndRef import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.StateRef import net.corda.core.contracts.StateRef

View File

@ -13,7 +13,7 @@ import io.requery.query.RowExpression
import net.corda.contracts.asset.Cash import net.corda.contracts.asset.Cash
import net.corda.contracts.asset.OnLedgerAsset import net.corda.contracts.asset.OnLedgerAsset
import net.corda.core.internal.ThreadBox import net.corda.core.internal.ThreadBox
import net.corda.core.bufferUntilSubscribed import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.crypto.SecureHash import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.containsAny import net.corda.core.crypto.containsAny
@ -30,7 +30,7 @@ import net.corda.core.serialization.SerializationDefaults.STORAGE_CONTEXT
import net.corda.core.serialization.SingletonSerializeAsToken import net.corda.core.serialization.SingletonSerializeAsToken
import net.corda.core.serialization.deserialize import net.corda.core.serialization.deserialize
import net.corda.core.serialization.serialize import net.corda.core.serialization.serialize
import net.corda.core.tee import net.corda.core.internal.tee
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder
import net.corda.core.transactions.WireTransaction import net.corda.core.transactions.WireTransaction
import net.corda.core.utilities.* import net.corda.core.utilities.*

View File

@ -12,10 +12,7 @@ import com.google.common.util.concurrent.SettableFuture
import net.corda.core.* import net.corda.core.*
import net.corda.core.flows.FlowInitiator import net.corda.core.flows.FlowInitiator
import net.corda.core.flows.FlowLogic import net.corda.core.flows.FlowLogic
import net.corda.core.internal.FlowStateMachine import net.corda.core.internal.*
import net.corda.core.internal.createDirectories
import net.corda.core.internal.div
import net.corda.core.internal.write
import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.CordaRPCOps
import net.corda.core.messaging.StateMachineUpdate import net.corda.core.messaging.StateMachineUpdate
import net.corda.core.internal.Emoji import net.corda.core.internal.Emoji

View File

@ -19,6 +19,7 @@ import net.corda.core.identity.AnonymousParty
import net.corda.core.identity.AnonymousPartyAndPath import net.corda.core.identity.AnonymousPartyAndPath
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.internal.FlowStateMachine import net.corda.core.internal.FlowStateMachine
import net.corda.core.internal.rootCause
import net.corda.core.map import net.corda.core.map
import net.corda.core.messaging.DataFeed import net.corda.core.messaging.DataFeed
import net.corda.core.messaging.SingleMessageRecipient import net.corda.core.messaging.SingleMessageRecipient
@ -26,8 +27,6 @@ import net.corda.core.messaging.StateMachineTransactionMapping
import net.corda.core.node.NodeInfo import net.corda.core.node.NodeInfo
import net.corda.core.node.services.ServiceInfo import net.corda.core.node.services.ServiceInfo
import net.corda.core.node.services.Vault import net.corda.core.node.services.Vault
import net.corda.core.rootCause
import net.corda.core.serialization.serialize
import net.corda.core.toFuture import net.corda.core.toFuture
import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.SignedTransaction
import net.corda.core.transactions.TransactionBuilder import net.corda.core.transactions.TransactionBuilder

View File

@ -1,8 +1,8 @@
package net.corda.node.utilities package net.corda.node.utilities
import com.google.common.util.concurrent.SettableFuture import com.google.common.util.concurrent.SettableFuture
import net.corda.core.bufferUntilSubscribed import net.corda.core.internal.bufferUntilSubscribed
import net.corda.core.tee import net.corda.core.internal.tee
import net.corda.testing.node.makeTestDataSourceProperties import net.corda.testing.node.makeTestDataSourceProperties
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.junit.After import org.junit.After

View File

@ -5,7 +5,7 @@ import com.nhaarman.mockito_kotlin.eq
import com.nhaarman.mockito_kotlin.mock import com.nhaarman.mockito_kotlin.mock
import net.corda.core.crypto.* import net.corda.core.crypto.*
import net.corda.core.internal.exists import net.corda.core.internal.exists
import net.corda.core.toTypedArray import net.corda.core.internal.toTypedArray
import net.corda.node.utilities.loadKeyStore import net.corda.node.utilities.loadKeyStore
import net.corda.testing.ALICE import net.corda.testing.ALICE
import net.corda.testing.getTestX509Name import net.corda.testing.getTestX509Name

View File

@ -3,7 +3,6 @@ package net.corda.attachmentdemo
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import joptsimple.OptionParser import joptsimple.OptionParser
import net.corda.client.rpc.CordaRPCClient import net.corda.client.rpc.CordaRPCClient
import net.corda.core.InputStreamAndHash
import net.corda.core.contracts.Contract import net.corda.core.contracts.Contract
import net.corda.core.contracts.ContractState import net.corda.core.contracts.ContractState
import net.corda.core.contracts.TransactionType import net.corda.core.contracts.TransactionType
@ -15,6 +14,7 @@ import net.corda.core.getOrThrow
import net.corda.core.identity.AbstractParty import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.internal.Emoji import net.corda.core.internal.Emoji
import net.corda.core.internal.InputStreamAndHash
import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.CordaRPCOps
import net.corda.core.messaging.startTrackedFlow import net.corda.core.messaging.startTrackedFlow
import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.LedgerTransaction

View File

@ -6,7 +6,6 @@ import net.corda.contracts.asset.CASH
import net.corda.contracts.asset.Cash import net.corda.contracts.asset.Cash
import net.corda.contracts.asset.`issued by` import net.corda.contracts.asset.`issued by`
import net.corda.contracts.asset.`owned by` import net.corda.contracts.asset.`owned by`
import net.corda.core.bd
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.crypto.MerkleTreeException import net.corda.core.crypto.MerkleTreeException
import net.corda.core.crypto.generateKeyPair import net.corda.core.crypto.generateKeyPair
@ -81,7 +80,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
val q = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M") val q = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
val res = oracle.query(listOf(q)) val res = oracle.query(listOf(q))
assertEquals(1, res.size) assertEquals(1, res.size)
assertEquals("0.678".bd, res[0].value) assertEquals(BigDecimal("0.678"), res[0].value)
assertEquals(q, res[0].of) assertEquals(q, res[0].of)
} }
} }
@ -163,7 +162,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
database.transaction { database.transaction {
val tx = makeTX() val tx = makeTX()
val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M") val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
val badFix = Fix(fixOf, "0.6789".bd) val badFix = Fix(fixOf, BigDecimal("0.6789"))
tx.addCommand(badFix, oracle.identity.owningKey) tx.addCommand(badFix, oracle.identity.owningKey)
val wtx = tx.toWireTransaction() val wtx = tx.toWireTransaction()
val ftx = wtx.buildFilteredTransaction(Predicate { x -> fixCmdFilter(x) }) val ftx = wtx.buildFilteredTransaction(Predicate { x -> fixCmdFilter(x) })
@ -212,7 +211,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
val tx = TransactionType.General.Builder(null) val tx = TransactionType.General.Builder(null)
val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M") val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
val oracle = n2.info.serviceIdentities(NodeInterestRates.Oracle.type).first() val oracle = n2.info.serviceIdentities(NodeInterestRates.Oracle.type).first()
val flow = FilteredRatesFlow(tx, oracle, fixOf, "0.675".bd, "0.1".bd) val flow = FilteredRatesFlow(tx, oracle, fixOf, BigDecimal("0.675"), BigDecimal("0.1"))
LogHelper.setLevel("rates") LogHelper.setLevel("rates")
mockNet.runNetwork() mockNet.runNetwork()
val future = n1.services.startFlow(flow).resultFuture val future = n1.services.startFlow(flow).resultFuture
@ -221,7 +220,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
// We should now have a valid fix of our tx from the oracle. // We should now have a valid fix of our tx from the oracle.
val fix = tx.toWireTransaction().commands.map { it.value as Fix }.first() val fix = tx.toWireTransaction().commands.map { it.value as Fix }.first()
assertEquals(fixOf, fix.of) assertEquals(fixOf, fix.of)
assertEquals("0.678".bd, fix.value) assertEquals(BigDecimal("0.678"), fix.value)
mockNet.stopNodes() mockNet.stopNodes()
} }

View File

@ -11,8 +11,8 @@ import net.corda.node.utilities.ServiceIdentityGenerator
import net.corda.cordform.CordformDefinition import net.corda.cordform.CordformDefinition
import net.corda.cordform.CordformContext import net.corda.cordform.CordformContext
import net.corda.cordform.CordformNode import net.corda.cordform.CordformNode
import net.corda.core.stream import net.corda.core.internal.stream
import net.corda.core.toTypedArray import net.corda.core.internal.toTypedArray
import net.corda.core.utilities.NetworkHostAndPort import net.corda.core.utilities.NetworkHostAndPort
import net.corda.node.services.transactions.minCorrectReplicas import net.corda.node.services.transactions.minCorrectReplicas
import org.bouncycastle.asn1.x500.X500Name import org.bouncycastle.asn1.x500.X500Name

View File

@ -3,11 +3,12 @@ package net.corda.vega.portfolio
import net.corda.client.rpc.notUsed import net.corda.client.rpc.notUsed
import net.corda.core.contracts.* import net.corda.core.contracts.*
import net.corda.core.identity.Party import net.corda.core.identity.Party
import net.corda.core.internal.sum
import net.corda.core.messaging.CordaRPCOps import net.corda.core.messaging.CordaRPCOps
import net.corda.core.node.ServiceHub import net.corda.core.node.ServiceHub
import net.corda.core.sum
import net.corda.vega.contracts.IRSState import net.corda.vega.contracts.IRSState
import net.corda.vega.contracts.SwapData import net.corda.vega.contracts.SwapData
import java.math.BigDecimal
import java.time.LocalDate import java.time.LocalDate
/** /**
@ -22,7 +23,7 @@ data class Portfolio(private val tradeStateAndRefs: List<StateAndRef<IRSState>>,
val swaps: List<SwapData> by lazy { trades.map { it.swap } } val swaps: List<SwapData> by lazy { trades.map { it.swap } }
val refs: List<StateRef> by lazy { tradeStateAndRefs.map { it.ref } } val refs: List<StateRef> by lazy { tradeStateAndRefs.map { it.ref } }
fun getNotionalForParty(party: Party) = trades.map { it.swap.getLegForParty(party).notional }.sum() fun getNotionalForParty(party: Party): BigDecimal = trades.map { it.swap.getLegForParty(party).notional }.sum()
fun update(curTrades: List<StateAndRef<IRSState>>): Portfolio { fun update(curTrades: List<StateAndRef<IRSState>>): Portfolio {
return copy(tradeStateAndRefs = curTrades) return copy(tradeStateAndRefs = curTrades)

View File

@ -4,6 +4,7 @@ import net.corda.core.internal.until
import net.corda.core.serialization.SerializeAsToken import net.corda.core.serialization.SerializeAsToken
import net.corda.core.serialization.SerializeAsTokenContext import net.corda.core.serialization.SerializeAsTokenContext
import net.corda.core.serialization.SingletonSerializationToken.Companion.singletonSerializationToken import net.corda.core.serialization.SingletonSerializationToken.Companion.singletonSerializationToken
import net.corda.core.internal.until
import net.corda.node.utilities.MutableClock import net.corda.node.utilities.MutableClock
import java.time.Clock import java.time.Clock
import java.time.Duration import java.time.Duration

View File

@ -4,7 +4,7 @@ package net.corda.webserver
import com.typesafe.config.ConfigException import com.typesafe.config.ConfigException
import net.corda.core.internal.div import net.corda.core.internal.div
import net.corda.core.rootCause import net.corda.core.internal.rootCause
import net.corda.webserver.internal.NodeWebServer import net.corda.webserver.internal.NodeWebServer
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.lang.management.ManagementFactory import java.lang.management.ManagementFactory