mirror of
https://github.com/corda/corda.git
synced 2025-01-27 14:49:35 +00:00
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:
parent
8acbd86c70
commit
407b467f67
@ -2,7 +2,7 @@ package net.corda.client.jfx
|
||||
|
||||
import net.corda.client.jfx.model.NodeMonitorModel
|
||||
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.DOLLARS
|
||||
import net.corda.core.contracts.USD
|
||||
|
@ -1,7 +1,7 @@
|
||||
package net.corda.client.rpc.internal
|
||||
|
||||
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.serialization.SerializationContext
|
||||
import net.corda.core.serialization.SerializationDefaults
|
||||
|
@ -5,7 +5,7 @@ import com.google.common.hash.HashingInputStream
|
||||
import net.corda.client.rpc.CordaRPCConnection
|
||||
import net.corda.client.rpc.notUsed
|
||||
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.crypto.SecureHash
|
||||
import net.corda.core.getOrThrow
|
||||
|
@ -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>
|
@ -1,49 +1,18 @@
|
||||
// TODO Move out the Kotlin specific stuff into a separate file
|
||||
@file:JvmName("Utils")
|
||||
|
||||
package net.corda.core
|
||||
|
||||
import com.google.common.base.Throwables
|
||||
import com.google.common.io.ByteStreams
|
||||
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 rx.Observable
|
||||
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.util.concurrent.CompletableFuture
|
||||
import java.util.concurrent.ExecutionException
|
||||
import java.util.concurrent.Future
|
||||
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.
|
||||
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)
|
||||
// TODO Delete this file once the Future stuff is out of here
|
||||
|
||||
/** 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 {
|
||||
@ -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
|
||||
* 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() {}
|
||||
}
|
||||
|
||||
/** 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" }
|
||||
|
@ -1,5 +1,8 @@
|
||||
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 java.math.BigDecimal
|
||||
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> {
|
||||
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.
|
||||
* 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 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.
|
||||
* @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.
|
||||
*/
|
||||
@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"
|
||||
}
|
||||
return if (other.source == source) {
|
||||
AmountTransfer(Math.addExact(quantityDelta, other.quantityDelta), token, source, destination)
|
||||
AmountTransfer(quantityDelta exactAdd other.quantityDelta, token, source, destination)
|
||||
} else {
|
||||
AmountTransfer(Math.subtractExact(quantityDelta, other.quantityDelta), token, source, destination)
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import net.corda.core.crypto.composite.CompositeKey.NodeAndWeight
|
||||
import net.corda.core.crypto.keys
|
||||
import net.corda.core.crypto.provider.CordaObjectIdentifier
|
||||
import net.corda.core.crypto.toStringShort
|
||||
import net.corda.core.utilities.exactAdd
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.utilities.sequence
|
||||
import org.bouncycastle.asn1.*
|
||||
@ -126,7 +127,7 @@ class CompositeKey private constructor(val threshold: Int, children: List<NodeAn
|
||||
var sum = 0
|
||||
for ((_, weight) in children) {
|
||||
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
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
package net.corda.core.flows
|
||||
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.core.abbreviate
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.FlowStateMachine
|
||||
import net.corda.core.internal.abbreviate
|
||||
import net.corda.core.messaging.DataFeed
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
|
@ -1,7 +1,7 @@
|
||||
package net.corda.core.flows
|
||||
|
||||
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.getOrThrow
|
||||
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 }
|
||||
nextRequests.addAll(inputHashes)
|
||||
|
||||
limitCounter = limitCounter checkedAdd nextRequests.size
|
||||
limitCounter = limitCounter exactAdd nextRequests.size
|
||||
if (limitCounter > limit)
|
||||
throw ExcessivelyLargeTransactionGraph()
|
||||
}
|
||||
|
@ -1,17 +1,37 @@
|
||||
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.OutputStream
|
||||
import java.lang.reflect.Field
|
||||
import java.math.BigDecimal
|
||||
import java.nio.charset.Charset
|
||||
import java.nio.charset.StandardCharsets.UTF_8
|
||||
import java.nio.file.*
|
||||
import java.nio.file.attribute.FileAttribute
|
||||
import java.time.Duration
|
||||
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.StreamSupport
|
||||
import java.util.zip.Deflater
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipOutputStream
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
inline val Throwable.rootCause: Throwable get() = Throwables.getRootCause(this)
|
||||
|
||||
infix fun Temporal.until(endExclusive: Temporal): Duration = Duration.between(this, endExclusive)
|
||||
|
||||
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 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.createDirectories(vararg attrs: FileAttribute<*>): Path = Files.createDirectories(this, *attrs)
|
||||
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 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
|
||||
|
||||
/** Returns a [DeclaredField] wrapper around the declared (possibly non-public) static field of the receiver [Class]. */
|
||||
|
@ -6,8 +6,7 @@ import net.corda.core.identity.AbstractParty
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.messaging.DataFeed
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.randomOrNull
|
||||
import net.corda.core.internal.randomOrNull
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import rx.Observable
|
||||
@ -98,9 +97,9 @@ interface NetworkMapCache {
|
||||
|
||||
/** Gets a notary identity by the given name. */
|
||||
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 }
|
||||
}
|
||||
}.randomOrNull()
|
||||
return notaryNode?.notaryIdentity
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
package net.corda.core.serialization.amqp
|
||||
|
||||
import net.corda.core.checkNotUnorderedHashMap
|
||||
import org.apache.qpid.proton.codec.Data
|
||||
import java.io.NotSerializableException
|
||||
import java.lang.reflect.ParameterizedType
|
||||
@ -47,9 +46,9 @@ class MapSerializer(val declaredType: ParameterizedType, factory: SerializerFact
|
||||
// Write map
|
||||
data.putMap()
|
||||
data.enter()
|
||||
for (entry in obj as Map<*, *>) {
|
||||
output.writeObjectOrNull(entry.key, data, declaredType.actualTypeArguments[0])
|
||||
output.writeObjectOrNull(entry.value, data, declaredType.actualTypeArguments[1])
|
||||
for ((key, value) in obj as Map<*, *>) {
|
||||
output.writeObjectOrNull(key, data, declaredType.actualTypeArguments[0])
|
||||
output.writeObjectOrNull(value, data, declaredType.actualTypeArguments[1])
|
||||
}
|
||||
data.exit() // exit map
|
||||
}
|
||||
@ -64,4 +63,10 @@ class MapSerializer(val declaredType: ParameterizedType, factory: SerializerFact
|
||||
private fun readEntry(schema: Schema, input: DeserializationInput, entry: Map.Entry<Any?, Any?>) =
|
||||
input.readObjectOrNull(entry.key, schema, declaredType.actualTypeArguments[0]) to
|
||||
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.")
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@ package net.corda.core.serialization.amqp
|
||||
|
||||
import com.google.common.primitives.Primitives
|
||||
import com.google.common.reflect.TypeResolver
|
||||
import net.corda.core.checkNotUnorderedHashMap
|
||||
import net.corda.core.serialization.AllWhitelist
|
||||
import net.corda.core.serialization.ClassWhitelist
|
||||
import net.corda.core.serialization.CordaSerializable
|
||||
|
@ -2,7 +2,7 @@ package net.corda.core.transactions
|
||||
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.indexOfOrThrow
|
||||
import net.corda.core.internal.indexOfOrThrow
|
||||
import net.corda.core.internal.castIfPossible
|
||||
import java.security.PublicKey
|
||||
import java.util.*
|
||||
|
@ -8,10 +8,17 @@ import kotlin.reflect.KProperty
|
||||
|
||||
//
|
||||
// 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
|
||||
// is also relevant to Java then put it in Utils.kt.
|
||||
// This is a collection of public utilities useful only for Kotlin code. Think carefully before adding anything here and
|
||||
// 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
|
||||
*
|
||||
|
@ -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) }
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
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.addOrReplaceCertificate
|
||||
import net.corda.node.utilities.addOrReplaceKey
|
||||
|
@ -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.createSelfSignedCACertificate
|
||||
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.utilities.*
|
||||
import net.corda.testing.MEGA_CORP
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -240,7 +240,7 @@ class SerializationOutputTests {
|
||||
serdes(obj)
|
||||
}
|
||||
|
||||
@Test(expected = NotSerializableException::class)
|
||||
@Test(expected = IllegalArgumentException::class)
|
||||
fun `test dislike of HashMap`() {
|
||||
val obj = WrapHashMap(HashMap<String, String>())
|
||||
serdes(obj)
|
||||
|
@ -11,4 +11,13 @@ This section describes the APIs that are available for the development of CorDap
|
||||
* :doc:`api-flows`
|
||||
* :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``
|
||||
|
@ -47,6 +47,9 @@ UNRELEASED
|
||||
* 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.
|
||||
|
||||
* 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
|
||||
------------
|
||||
|
||||
|
@ -5,11 +5,10 @@ package net.corda.nodeapi
|
||||
import com.esotericsoftware.kryo.Registration
|
||||
import com.esotericsoftware.kryo.Serializer
|
||||
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.toFuture
|
||||
import net.corda.core.toObservable
|
||||
import net.corda.core.CordaRuntimeException
|
||||
import net.corda.nodeapi.config.OldConfig
|
||||
import rx.Observable
|
||||
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")
|
||||
return super.getRegistration(type)
|
||||
}
|
||||
|
||||
private fun Class<*>.requireExternal(msg: String) {
|
||||
require(!name.startsWith("net.corda.node.") && !name.contains(".internal.")) { "$msg: $name" }
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package net.corda.nodeapi.config
|
||||
|
||||
import com.typesafe.config.Config
|
||||
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.NetworkHostAndPort
|
||||
import net.corda.core.utilities.parseNetworkHostAndPort
|
||||
|
@ -1,6 +1,6 @@
|
||||
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.POUNDS
|
||||
import net.corda.core.identity.Party
|
||||
|
@ -1,7 +1,7 @@
|
||||
package net.corda.node.services.statemachine
|
||||
|
||||
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.flows.*
|
||||
import net.corda.core.identity.Party
|
||||
|
@ -3,8 +3,8 @@ package net.corda.services.messaging
|
||||
import com.google.common.util.concurrent.Futures
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import net.corda.core.crypto.random63BitValue
|
||||
import net.corda.core.elapsedTime
|
||||
import net.corda.core.getOrThrow
|
||||
import net.corda.core.internal.elapsedTime
|
||||
import net.corda.core.internal.times
|
||||
import net.corda.core.messaging.MessageRecipients
|
||||
import net.corda.core.messaging.SingleMessageRecipient
|
||||
|
@ -6,11 +6,9 @@ import joptsimple.OptionException
|
||||
import net.corda.core.*
|
||||
import net.corda.core.crypto.commonName
|
||||
import net.corda.core.crypto.orgName
|
||||
import net.corda.core.internal.createDirectories
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.node.VersionInfo
|
||||
import net.corda.core.node.services.ServiceInfo
|
||||
import net.corda.core.internal.Emoji
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.node.ArgsParser
|
||||
import net.corda.node.CmdLineOptions
|
||||
|
@ -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.internal.ThreadBox
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.internal.noneOrSingle
|
||||
import net.corda.core.node.NodeInfo
|
||||
import net.corda.core.node.services.NetworkMapCache
|
||||
import net.corda.core.node.services.NetworkMapCache.MapChange
|
||||
|
@ -3,7 +3,7 @@ package net.corda.node.services.network
|
||||
import com.google.common.annotations.VisibleForTesting
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
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.Party
|
||||
import net.corda.core.map
|
||||
|
@ -1,7 +1,7 @@
|
||||
package net.corda.node.services.persistence
|
||||
|
||||
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.flows.StateMachineRunId
|
||||
import net.corda.core.messaging.DataFeed
|
||||
|
@ -1,7 +1,7 @@
|
||||
package net.corda.node.services.persistence
|
||||
|
||||
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.messaging.DataFeed
|
||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||
|
@ -1,7 +1,7 @@
|
||||
package net.corda.node.services.persistence
|
||||
|
||||
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.flows.StateMachineRunId
|
||||
import net.corda.core.messaging.DataFeed
|
||||
|
@ -6,12 +6,12 @@ import co.paralleluniverse.fibers.Suspendable
|
||||
import co.paralleluniverse.strands.Strand
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import com.google.common.util.concurrent.SettableFuture
|
||||
import net.corda.core.abbreviate
|
||||
import net.corda.core.crypto.SecureHash
|
||||
import net.corda.core.crypto.random63BitValue
|
||||
import net.corda.core.flows.*
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.FlowStateMachine
|
||||
import net.corda.core.internal.abbreviate
|
||||
import net.corda.core.internal.staticField
|
||||
import net.corda.core.transactions.SignedTransaction
|
||||
import net.corda.core.utilities.*
|
||||
@ -122,7 +122,7 @@ class FlowStateMachineImpl<R>(override val id: StateMachineRunId,
|
||||
actionOnEnd(Try.Success(result), false)
|
||||
_resultFuture?.set(result)
|
||||
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() {
|
||||
|
@ -9,7 +9,7 @@ import com.google.common.collect.HashMultimap
|
||||
import com.google.common.util.concurrent.ListenableFuture
|
||||
import com.google.common.util.concurrent.MoreExecutors
|
||||
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.random63BitValue
|
||||
import net.corda.core.flows.FlowException
|
||||
|
@ -27,7 +27,7 @@ import net.corda.core.serialization.CordaSerializable
|
||||
import net.corda.core.serialization.SingletonSerializeAsToken
|
||||
import net.corda.core.serialization.deserialize
|
||||
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.SignedTransaction
|
||||
import net.corda.core.utilities.debug
|
||||
|
@ -1,7 +1,7 @@
|
||||
package net.corda.node.services.vault
|
||||
|
||||
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.StateAndRef
|
||||
import net.corda.core.contracts.StateRef
|
||||
|
@ -13,7 +13,7 @@ import io.requery.query.RowExpression
|
||||
import net.corda.contracts.asset.Cash
|
||||
import net.corda.contracts.asset.OnLedgerAsset
|
||||
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.crypto.SecureHash
|
||||
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.deserialize
|
||||
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.WireTransaction
|
||||
import net.corda.core.utilities.*
|
||||
|
@ -12,10 +12,7 @@ import com.google.common.util.concurrent.SettableFuture
|
||||
import net.corda.core.*
|
||||
import net.corda.core.flows.FlowInitiator
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.internal.FlowStateMachine
|
||||
import net.corda.core.internal.createDirectories
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.internal.write
|
||||
import net.corda.core.internal.*
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.messaging.StateMachineUpdate
|
||||
import net.corda.core.internal.Emoji
|
||||
|
@ -19,6 +19,7 @@ import net.corda.core.identity.AnonymousParty
|
||||
import net.corda.core.identity.AnonymousPartyAndPath
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.FlowStateMachine
|
||||
import net.corda.core.internal.rootCause
|
||||
import net.corda.core.map
|
||||
import net.corda.core.messaging.DataFeed
|
||||
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.services.ServiceInfo
|
||||
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.transactions.SignedTransaction
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
|
@ -1,8 +1,8 @@
|
||||
package net.corda.node.utilities
|
||||
|
||||
import com.google.common.util.concurrent.SettableFuture
|
||||
import net.corda.core.bufferUntilSubscribed
|
||||
import net.corda.core.tee
|
||||
import net.corda.core.internal.bufferUntilSubscribed
|
||||
import net.corda.core.internal.tee
|
||||
import net.corda.testing.node.makeTestDataSourceProperties
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.junit.After
|
||||
|
@ -5,7 +5,7 @@ import com.nhaarman.mockito_kotlin.eq
|
||||
import com.nhaarman.mockito_kotlin.mock
|
||||
import net.corda.core.crypto.*
|
||||
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.testing.ALICE
|
||||
import net.corda.testing.getTestX509Name
|
||||
|
@ -3,7 +3,6 @@ package net.corda.attachmentdemo
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import joptsimple.OptionParser
|
||||
import net.corda.client.rpc.CordaRPCClient
|
||||
import net.corda.core.InputStreamAndHash
|
||||
import net.corda.core.contracts.Contract
|
||||
import net.corda.core.contracts.ContractState
|
||||
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.Party
|
||||
import net.corda.core.internal.Emoji
|
||||
import net.corda.core.internal.InputStreamAndHash
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.messaging.startTrackedFlow
|
||||
import net.corda.core.transactions.LedgerTransaction
|
||||
|
@ -6,7 +6,6 @@ import net.corda.contracts.asset.CASH
|
||||
import net.corda.contracts.asset.Cash
|
||||
import net.corda.contracts.asset.`issued by`
|
||||
import net.corda.contracts.asset.`owned by`
|
||||
import net.corda.core.bd
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.crypto.MerkleTreeException
|
||||
import net.corda.core.crypto.generateKeyPair
|
||||
@ -81,7 +80,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
|
||||
val q = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
|
||||
val res = oracle.query(listOf(q))
|
||||
assertEquals(1, res.size)
|
||||
assertEquals("0.678".bd, res[0].value)
|
||||
assertEquals(BigDecimal("0.678"), res[0].value)
|
||||
assertEquals(q, res[0].of)
|
||||
}
|
||||
}
|
||||
@ -163,7 +162,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
|
||||
database.transaction {
|
||||
val tx = makeTX()
|
||||
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)
|
||||
val wtx = tx.toWireTransaction()
|
||||
val ftx = wtx.buildFilteredTransaction(Predicate { x -> fixCmdFilter(x) })
|
||||
@ -212,7 +211,7 @@ class NodeInterestRatesTest : TestDependencyInjectionBase() {
|
||||
val tx = TransactionType.General.Builder(null)
|
||||
val fixOf = NodeInterestRates.parseFixOf("LIBOR 2016-03-16 1M")
|
||||
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")
|
||||
mockNet.runNetwork()
|
||||
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.
|
||||
val fix = tx.toWireTransaction().commands.map { it.value as Fix }.first()
|
||||
assertEquals(fixOf, fix.of)
|
||||
assertEquals("0.678".bd, fix.value)
|
||||
assertEquals(BigDecimal("0.678"), fix.value)
|
||||
mockNet.stopNodes()
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,8 @@ import net.corda.node.utilities.ServiceIdentityGenerator
|
||||
import net.corda.cordform.CordformDefinition
|
||||
import net.corda.cordform.CordformContext
|
||||
import net.corda.cordform.CordformNode
|
||||
import net.corda.core.stream
|
||||
import net.corda.core.toTypedArray
|
||||
import net.corda.core.internal.stream
|
||||
import net.corda.core.internal.toTypedArray
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.node.services.transactions.minCorrectReplicas
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
|
@ -3,11 +3,12 @@ package net.corda.vega.portfolio
|
||||
import net.corda.client.rpc.notUsed
|
||||
import net.corda.core.contracts.*
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.internal.sum
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.node.ServiceHub
|
||||
import net.corda.core.sum
|
||||
import net.corda.vega.contracts.IRSState
|
||||
import net.corda.vega.contracts.SwapData
|
||||
import java.math.BigDecimal
|
||||
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 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 {
|
||||
return copy(tradeStateAndRefs = curTrades)
|
||||
|
@ -4,6 +4,7 @@ import net.corda.core.internal.until
|
||||
import net.corda.core.serialization.SerializeAsToken
|
||||
import net.corda.core.serialization.SerializeAsTokenContext
|
||||
import net.corda.core.serialization.SingletonSerializationToken.Companion.singletonSerializationToken
|
||||
import net.corda.core.internal.until
|
||||
import net.corda.node.utilities.MutableClock
|
||||
import java.time.Clock
|
||||
import java.time.Duration
|
||||
|
@ -4,7 +4,7 @@ package net.corda.webserver
|
||||
|
||||
import com.typesafe.config.ConfigException
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.rootCause
|
||||
import net.corda.core.internal.rootCause
|
||||
import net.corda.webserver.internal.NodeWebServer
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.lang.management.ManagementFactory
|
||||
|
Loading…
x
Reference in New Issue
Block a user