Minor: core: fix static analysis warnings.

One actual bug was found this way, albeit a harmless one.
This commit is contained in:
Mike Hearn
2017-04-11 15:52:04 +02:00
parent d35bd74596
commit 1a86ac481f
30 changed files with 44 additions and 156 deletions

View File

@ -80,9 +80,6 @@ dependencies {
// JPA 2.1 annotations. // JPA 2.1 annotations.
compile "org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final" compile "org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final"
// RS API: Response type and codes for ApiUtils.
compile "javax.ws.rs:javax.ws.rs-api:2.0.1"
// Requery: SQL based query & persistence for Kotlin // Requery: SQL based query & persistence for Kotlin
compile "io.requery:requery-kotlin:$requery_version" compile "io.requery:requery-kotlin:$requery_version"
} }

View File

@ -105,7 +105,7 @@ infix fun <T> ListenableFuture<T>.then(body: () -> Unit): ListenableFuture<T> =
infix fun <T> ListenableFuture<T>.success(body: (T) -> Unit): ListenableFuture<T> = apply { success(RunOnCallerThread, body) } infix fun <T> ListenableFuture<T>.success(body: (T) -> Unit): ListenableFuture<T> = apply { success(RunOnCallerThread, body) }
infix fun <T> ListenableFuture<T>.failure(body: (Throwable) -> Unit): ListenableFuture<T> = apply { failure(RunOnCallerThread, body) } infix fun <T> ListenableFuture<T>.failure(body: (Throwable) -> Unit): ListenableFuture<T> = apply { failure(RunOnCallerThread, body) }
@Suppress("UNCHECKED_CAST") // We need the awkward cast because otherwise F cannot be nullable, even though it's safe. @Suppress("UNCHECKED_CAST") // We need the awkward cast because otherwise F cannot be nullable, even though it's safe.
infix fun <F, T> ListenableFuture<F>.map(mapper: (F) -> T): ListenableFuture<T> = Futures.transform(this, Function { (mapper as (F?) -> T)(it) }) infix fun <F, T> ListenableFuture<F>.map(mapper: (F) -> T): ListenableFuture<T> = Futures.transform(this, { (mapper as (F?) -> T)(it) })
infix fun <F, T> ListenableFuture<F>.flatMap(mapper: (F) -> ListenableFuture<T>): ListenableFuture<T> = Futures.transformAsync(this) { mapper(it!!) } infix fun <F, T> ListenableFuture<F>.flatMap(mapper: (F) -> ListenableFuture<T>): ListenableFuture<T> = Futures.transformAsync(this) { mapper(it!!) }
/** Executes the given block and sets the future to either the result, or any exception that was thrown. */ /** Executes the given block and sets the future to either the result, or any exception that was thrown. */
@ -156,7 +156,7 @@ 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)
// Simple infix function to add back null safety that the JDK lacks: timeA until timeB // Simple infix function to add back null safety that the JDK lacks: timeA until timeB
infix fun Temporal.until(endExclusive: Temporal) = Duration.between(this, endExclusive) infix fun Temporal.until(endExclusive: Temporal): Duration = Duration.between(this, endExclusive)
/** Returns the index of the given item or throws [IllegalArgumentException] if not found. */ /** Returns the index of the given item or throws [IllegalArgumentException] if not found. */
fun <T> List<T>.indexOfOrThrow(item: T): Int { fun <T> List<T>.indexOfOrThrow(item: T): Int {
@ -349,6 +349,7 @@ data class InputStreamAndHash(val inputStream: InputStream, val sha256: SecureHa
val Throwable.rootCause: Throwable get() = Throwables.getRootCause(this) val Throwable.rootCause: Throwable get() = Throwables.getRootCause(this)
/** Representation of an operation that may have thrown an error. */ /** Representation of an operation that may have thrown an error. */
@Suppress("DataClassPrivateConstructor")
@CordaSerializable @CordaSerializable
data class ErrorOr<out A> private constructor(val value: A?, val error: Throwable?) { data class ErrorOr<out A> private constructor(val value: A?, val error: Throwable?) {
// The ErrorOr holds a value iff error == null // The ErrorOr holds a value iff error == null

View File

@ -103,18 +103,6 @@ inline fun <reified T : CommandData> Collection<AuthenticatedObject<CommandData>
fun <C : CommandData> Collection<AuthenticatedObject<CommandData>>.requireSingleCommand(klass: Class<C>) = fun <C : CommandData> Collection<AuthenticatedObject<CommandData>>.requireSingleCommand(klass: Class<C>) =
mapNotNull { @Suppress("UNCHECKED_CAST") if (klass.isInstance(it.value)) it as AuthenticatedObject<C> else null }.single() mapNotNull { @Suppress("UNCHECKED_CAST") if (klass.isInstance(it.value)) it as AuthenticatedObject<C> else null }.single()
/**
* Simple functionality for verifying a move command. Verifies that each input has a signature from its owning key.
*
* @param T the type of the move command.
*/
@Throws(IllegalArgumentException::class)
// TODO: Can we have a common Move command for all contracts and avoid the reified type parameter here?
inline fun <reified T : MoveCommand> verifyMoveCommand(inputs: List<OwnableState>,
tx: TransactionForContract)
: MoveCommand
= verifyMoveCommand<T>(inputs, tx.commands)
/** /**
* Simple functionality for verifying a move command. Verifies that each input has a signature from its owning key. * Simple functionality for verifying a move command. Verifies that each input has a signature from its owning key.
* *

View File

@ -267,7 +267,7 @@ fun <T : Any> Iterable<Amount<T>>.sumOrZero(token: T) = if (iterator().hasNext()
* @see SourceAndAmount.apply which processes a list of SourceAndAmount objects * @see SourceAndAmount.apply which processes a list of SourceAndAmount objects
* and calculates the resulting Amount distribution as a new list of SourceAndAmount objects. * and calculates the resulting Amount distribution as a new list of SourceAndAmount objects.
*/ */
data class SourceAndAmount<T : Any, P : Any>(val source: P, val amount: Amount<T>, val ref: Any? = null) data class SourceAndAmount<T : Any, out P : Any>(val source: P, val amount: Amount<T>, val ref: Any? = null)
/** /**
* This class represents a possibly negative transfer of tokens from one vault state to another, possibly at a future date. * This class represents a possibly negative transfer of tokens from one vault state to another, possibly at a future date.
@ -516,7 +516,7 @@ data class Tenor(val name: String) {
val adjustedMaturityDate = calendar.applyRollConvention(maturityDate, DateRollConvention.ModifiedFollowing) val adjustedMaturityDate = calendar.applyRollConvention(maturityDate, DateRollConvention.ModifiedFollowing)
val daysToMaturity = calculateDaysBetween(startDate, adjustedMaturityDate, DayCountBasisYear.Y360, DayCountBasisDay.DActual) val daysToMaturity = calculateDaysBetween(startDate, adjustedMaturityDate, DayCountBasisYear.Y360, DayCountBasisDay.DActual)
return daysToMaturity.toInt() return daysToMaturity
} }
override fun toString(): String = name override fun toString(): String = name
@ -645,7 +645,7 @@ open class BusinessCalendar private constructor(val holidayDates: List<LocalDate
}.toMap() }.toMap()
/** Parses a date of the form YYYY-MM-DD, like 2016-01-10 for 10th Jan. */ /** Parses a date of the form YYYY-MM-DD, like 2016-01-10 for 10th Jan. */
fun parseDateFromString(it: String) = LocalDate.parse(it, DateTimeFormatter.ISO_LOCAL_DATE) fun parseDateFromString(it: String): LocalDate = LocalDate.parse(it, DateTimeFormatter.ISO_LOCAL_DATE)
/** Returns a business calendar that combines all the named holiday calendars into one list of holiday dates. */ /** Returns a business calendar that combines all the named holiday calendars into one list of holiday dates. */
fun getInstance(vararg calname: String) = BusinessCalendar( fun getInstance(vararg calname: String) = BusinessCalendar(

View File

@ -52,7 +52,7 @@ interface MultilateralNettableState<out T : Any> {
val multilateralNetState: T val multilateralNetState: T
} }
interface NettableState<N : BilateralNettableState<N>, T : Any> : BilateralNettableState<N>, interface NettableState<N : BilateralNettableState<N>, out T : Any> : BilateralNettableState<N>,
MultilateralNettableState<T> MultilateralNettableState<T>
/** /**
@ -145,26 +145,13 @@ data class TransactionState<out T : ContractState> @JvmOverloads constructor(
* Note that an encumbered state that is being consumed must have its encumbrance consumed in the same transaction, * Note that an encumbered state that is being consumed must have its encumbrance consumed in the same transaction,
* otherwise the transaction is not valid. * otherwise the transaction is not valid.
*/ */
val encumbrance: Int? = null) { val encumbrance: Int? = null)
/**
* Copies the underlying state, replacing the notary field with the new value.
* To replace the notary, we need an approval (signature) from _all_ participants of the [ContractState].
*/
fun withNotary(newNotary: Party) = TransactionState(this.data, newNotary, encumbrance)
}
/** Wraps the [ContractState] in a [TransactionState] object */ /** Wraps the [ContractState] in a [TransactionState] object */
infix fun <T : ContractState> T.`with notary`(newNotary: Party) = withNotary(newNotary) infix fun <T : ContractState> T.`with notary`(newNotary: Party) = withNotary(newNotary)
infix fun <T : ContractState> T.withNotary(newNotary: Party) = TransactionState(this, newNotary) infix fun <T : ContractState> T.withNotary(newNotary: Party) = TransactionState(this, newNotary)
/**
* Marker interface for data classes that represent the issuance state for a contract. These are intended as templates
* from which the state object is initialised.
*/
interface IssuanceDefinition
/** /**
* Definition for an issued product, which can be cash, a cash-like thing, assets, or generally anything else that's * Definition for an issued product, which can be cash, a cash-like thing, assets, or generally anything else that's
* quantifiable with integer quantities. * quantifiable with integer quantities.
@ -243,7 +230,7 @@ interface LinearState : ContractState {
* Standard clause to verify the LinearState safety properties. * Standard clause to verify the LinearState safety properties.
*/ */
@CordaSerializable @CordaSerializable
class ClauseVerifier<S : LinearState, C : CommandData> : Clause<S, C, Unit>() { class ClauseVerifier<in S : LinearState, C : CommandData> : Clause<S, C, Unit>() {
override fun verify(tx: TransactionForContract, override fun verify(tx: TransactionForContract,
inputs: List<S>, inputs: List<S>,
outputs: List<S>, outputs: List<S>,
@ -360,7 +347,7 @@ inline fun <reified T : ContractState> Iterable<StateAndRef<ContractState>>.filt
data class PartyAndReference(val party: AnonymousParty, val reference: OpaqueBytes) { data class PartyAndReference(val party: AnonymousParty, val reference: OpaqueBytes) {
constructor(party: Party, reference: OpaqueBytes) : this(party.toAnonymous(), reference) constructor(party: Party, reference: OpaqueBytes) : this(party.toAnonymous(), reference)
override fun toString() = "${party}$reference" override fun toString() = "$party$reference"
} }
/** Marker interface for classes that represent commands */ /** Marker interface for classes that represent commands */

View File

@ -95,9 +95,6 @@ class AttachmentResolutionException(val hash: SecureHash) : FlowException() {
override fun toString(): String = "Attachment resolution failure for $hash" override fun toString(): String = "Attachment resolution failure for $hash"
} }
@CordaSerializable
class TransactionConflictException(val conflictRef: StateRef, val tx1: LedgerTransaction, val tx2: LedgerTransaction) : Exception()
sealed class TransactionVerificationException(val tx: LedgerTransaction, cause: Throwable?) : FlowException(cause) { sealed class TransactionVerificationException(val tx: LedgerTransaction, cause: Throwable?) : FlowException(cause) {
class ContractRejection(tx: LedgerTransaction, val contract: Contract, cause: Throwable?) : TransactionVerificationException(tx, cause) class ContractRejection(tx: LedgerTransaction, val contract: Contract, cause: Throwable?) : TransactionVerificationException(tx, cause)
class MoreThanOneNotary(tx: LedgerTransaction) : TransactionVerificationException(tx, null) class MoreThanOneNotary(tx: LedgerTransaction) : TransactionVerificationException(tx, null)

View File

@ -19,7 +19,7 @@ open class AllOf<S : ContractState, C : CommandData, K : Any>(firstClause: Claus
override fun matchedClauses(commands: List<AuthenticatedObject<C>>): List<Clause<S, C, K>> { override fun matchedClauses(commands: List<AuthenticatedObject<C>>): List<Clause<S, C, K>> {
clauses.forEach { clause -> clauses.forEach { clause ->
check(clause.matches(commands)) { "Failed to match clause ${clause}" } check(clause.matches(commands)) { "Failed to match clause $clause" }
} }
return clauses return clauses
} }

View File

@ -20,7 +20,7 @@ fun <C : CommandData> verifyClause(tx: TransactionForContract,
commands: List<AuthenticatedObject<C>>) { commands: List<AuthenticatedObject<C>>) {
if (Clause.log.isTraceEnabled) { if (Clause.log.isTraceEnabled) {
clause.getExecutionPath(commands).forEach { clause.getExecutionPath(commands).forEach {
Clause.log.trace("Tx ${tx.origHash} clause: ${clause}") Clause.log.trace("Tx ${tx.origHash} clause: $clause")
} }
} }
val matchedCommands = clause.verify(tx, tx.inputs, tx.outputs, commands, null) val matchedCommands = clause.verify(tx, tx.inputs, tx.outputs, commands, null)

View File

@ -8,7 +8,7 @@ import net.corda.core.contracts.TransactionForContract
/** /**
* Filter the states that are passed through to the wrapped clause, to restrict them to a specific type. * Filter the states that are passed through to the wrapped clause, to restrict them to a specific type.
*/ */
class FilterOn<S : ContractState, C : CommandData, K : Any>(val clause: Clause<S, C, K>, class FilterOn<S : ContractState, C : CommandData, in K : Any>(val clause: Clause<S, C, K>,
val filterStates: (List<ContractState>) -> List<S>) : Clause<ContractState, C, K>() { val filterStates: (List<ContractState>) -> List<S>) : Clause<ContractState, C, K>() {
override val requiredCommands: Set<Class<out CommandData>> override val requiredCommands: Set<Class<out CommandData>>
= clause.requiredCommands = clause.requiredCommands

View File

@ -10,7 +10,7 @@ import java.util.*
/** /**
* Compose a number of clauses, such that the first match is run, and it errors if none is run. * Compose a number of clauses, such that the first match is run, and it errors if none is run.
*/ */
class FirstOf<S : ContractState, C : CommandData, K : Any>(val firstClause: Clause<S, C, K>, vararg remainingClauses: Clause<S, C, K>) : CompositeClause<S, C, K>() { class FirstOf<S : ContractState, C : CommandData, K : Any>(firstClause: Clause<S, C, K>, vararg remainingClauses: Clause<S, C, K>) : CompositeClause<S, C, K>() {
companion object { companion object {
val logger = loggerFor<FirstOf<*, *, *>>() val logger = loggerFor<FirstOf<*, *, *>>()
} }

View File

@ -122,7 +122,7 @@ object Crypto {
* @return a currently supported SignatureScheme. * @return a currently supported SignatureScheme.
* @throws IllegalArgumentException if the requested signature scheme is not supported. * @throws IllegalArgumentException if the requested signature scheme is not supported.
*/ */
private fun findSignatureScheme(schemeCodeName: String): SignatureScheme = supportedSignatureSchemes[schemeCodeName] ?: throw IllegalArgumentException("Unsupported key/algorithm for metadata schemeCodeName: ${schemeCodeName}") private fun findSignatureScheme(schemeCodeName: String): SignatureScheme = supportedSignatureSchemes[schemeCodeName] ?: throw IllegalArgumentException("Unsupported key/algorithm for metadata schemeCodeName: $schemeCodeName")
/** /**
* Retrieve the corresponding [SignatureScheme] based on the type of the input [KeyPair]. * Retrieve the corresponding [SignatureScheme] based on the type of the input [KeyPair].

View File

@ -10,6 +10,7 @@ import net.i2p.crypto.eddsa.EdDSAEngine
import net.i2p.crypto.eddsa.EdDSAPrivateKey import net.i2p.crypto.eddsa.EdDSAPrivateKey
import net.i2p.crypto.eddsa.EdDSAPublicKey import net.i2p.crypto.eddsa.EdDSAPublicKey
import net.i2p.crypto.eddsa.KeyPairGenerator import net.i2p.crypto.eddsa.KeyPairGenerator
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveSpec
import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable import net.i2p.crypto.eddsa.spec.EdDSANamedCurveTable
import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec import net.i2p.crypto.eddsa.spec.EdDSAPrivateKeySpec
import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec import net.i2p.crypto.eddsa.spec.EdDSAPublicKeySpec
@ -72,7 +73,7 @@ fun PrivateKey.signWithECDSA(bytesToSign: ByteArray, publicKey: PublicKey): Digi
return DigitalSignature.WithKey(publicKey, signWithECDSA(bytesToSign).bytes) return DigitalSignature.WithKey(publicKey, signWithECDSA(bytesToSign).bytes)
} }
val ed25519Curve = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512) val ed25519Curve: EdDSANamedCurveSpec = EdDSANamedCurveTable.getByName(EdDSANamedCurveTable.CURVE_ED25519_SHA512)
// TODO We use for both CompositeKeys and EdDSAPublicKey custom Kryo serializers and deserializers. We need to specify encoding. // TODO We use for both CompositeKeys and EdDSAPublicKey custom Kryo serializers and deserializers. We need to specify encoding.
// TODO: follow the crypto-conditions ASN.1 spec, some changes are needed to be compatible with the condition // TODO: follow the crypto-conditions ASN.1 spec, some changes are needed to be compatible with the condition
@ -106,7 +107,7 @@ fun PublicKey.verifyWithECDSA(content: ByteArray, signature: DigitalSignature) {
val verifier = EdDSAEngine() val verifier = EdDSAEngine()
verifier.initVerify(pubKey) verifier.initVerify(pubKey)
verifier.update(content) verifier.update(content)
if (verifier.verify(signature.bytes) == false) if (!verifier.verify(signature.bytes))
throw SignatureException("Signature did not match") throw SignatureException("Signature did not match")
} }
@ -138,9 +139,9 @@ fun PublicKey.containsAny(otherKeys: Iterable<PublicKey>): Boolean {
fun Iterable<DigitalSignature.WithKey>.byKeys() = map { it.by }.toSet() fun Iterable<DigitalSignature.WithKey>.byKeys() = map { it.by }.toSet()
// Allow Kotlin destructuring: val (private, public) = keyPair // Allow Kotlin destructuring: val (private, public) = keyPair
operator fun KeyPair.component1() = this.private operator fun KeyPair.component1(): PrivateKey = this.private
operator fun KeyPair.component2() = this.public operator fun KeyPair.component2(): PublicKey = this.public
/** A simple wrapper that will make it easier to swap out the EC algorithm we use in future */ /** A simple wrapper that will make it easier to swap out the EC algorithm we use in future */
fun generateKeyPair(): KeyPair = KeyPairGenerator().generateKeyPair() fun generateKeyPair(): KeyPair = KeyPairGenerator().generateKeyPair()

View File

@ -7,6 +7,4 @@ import java.security.KeyFactory
* This is required as a [SignatureScheme] requires a [java.security.KeyFactory] property, but i2p has * This is required as a [SignatureScheme] requires a [java.security.KeyFactory] property, but i2p has
* its own KeyFactory for EdDSA, thus this actually a Proxy Pattern over i2p's KeyFactory. * its own KeyFactory for EdDSA, thus this actually a Proxy Pattern over i2p's KeyFactory.
*/ */
class EdDSAKeyFactory : KeyFactory { class EdDSAKeyFactory : KeyFactory(net.i2p.crypto.eddsa.KeyFactory(), null, "EDDSA_ED25519_SHA512")
constructor() : super(net.i2p.crypto.eddsa.KeyFactory(), null, "EDDSA_ED25519_SHA512")
}

View File

@ -24,7 +24,7 @@ import java.security.PublicKey
*/ */
class Party(val name: String, owningKey: PublicKey) : AbstractParty(owningKey) { class Party(val name: String, owningKey: PublicKey) : AbstractParty(owningKey) {
override fun toAnonymous(): AnonymousParty = AnonymousParty(owningKey) override fun toAnonymous(): AnonymousParty = AnonymousParty(owningKey)
override fun toString() = "${owningKey.toBase58String()} (${name})" override fun toString() = "${owningKey.toBase58String()} ($name)"
override fun nameOrNull(): String? = name override fun nameOrNull(): String? = name
override fun ref(bytes: OpaqueBytes): PartyAndReference = PartyAndReference(this.toAnonymous(), bytes) override fun ref(bytes: OpaqueBytes): PartyAndReference = PartyAndReference(this.toAnonymous(), bytes)

View File

@ -16,10 +16,9 @@ import java.util.*
* has at least one flow, but that flow may also invoke sub-flows: they all share the same run id. * has at least one flow, but that flow may also invoke sub-flows: they all share the same run id.
*/ */
@CordaSerializable @CordaSerializable
data class StateMachineRunId private constructor(val uuid: UUID) { data class StateMachineRunId(val uuid: UUID) {
companion object { companion object {
fun createRandom(): StateMachineRunId = StateMachineRunId(UUID.randomUUID()) fun createRandom(): StateMachineRunId = StateMachineRunId(UUID.randomUUID())
fun wrap(uuid: UUID): StateMachineRunId = StateMachineRunId(uuid)
} }
override fun toString(): String = "[$uuid]" override fun toString(): String = "[$uuid]"

View File

@ -14,7 +14,7 @@ data class ServiceInfo(val type: ServiceType, val name: String? = null) {
companion object { companion object {
fun parse(encoded: String): ServiceInfo { fun parse(encoded: String): ServiceInfo {
val parts = encoded.split("|") val parts = encoded.split("|")
require(parts.size > 0 && parts.size <= 2) { "Invalid number of elements found" } require(parts.size in 1..2) { "Invalid number of elements found" }
val type = ServiceType.parse(parts[0]) val type = ServiceType.parse(parts[0])
val name = parts.getOrNull(1) val name = parts.getOrNull(1)
return ServiceInfo(type, name) return ServiceInfo(type, name)

View File

@ -57,15 +57,10 @@ abstract class MappedSchema(schemaFamily: Class<*>,
@Embeddable @Embeddable
data class PersistentStateRef( data class PersistentStateRef(
@Column(name = "transaction_id", length = 64) @Column(name = "transaction_id", length = 64)
var txId: String?, var txId: String? = null,
@Column(name = "output_index") @Column(name = "output_index")
var index: Int? var index: Int? = null
) : Serializable { ) : Serializable {
constructor(stateRef: StateRef) : this(stateRef.txhash.bytes.toHexString(), stateRef.index) constructor(stateRef: StateRef) : this(stateRef.txhash.bytes.toHexString(), stateRef.index)
/*
JPA Query requirement:
@Entity classes should have a default (non-arg) constructor to instantiate the objects when retrieving them from the database.
*/
constructor() : this(null, null)
} }

View File

@ -35,5 +35,5 @@ open class OpaqueBytes(val bytes: ByteArray) {
} }
fun ByteArray.opaque(): OpaqueBytes = OpaqueBytes(this) fun ByteArray.opaque(): OpaqueBytes = OpaqueBytes(this)
fun ByteArray.toHexString() = BaseEncoding.base16().encode(this) fun ByteArray.toHexString(): String = BaseEncoding.base16().encode(this)
fun String.parseAsHex() = BaseEncoding.base16().decode(this) fun String.parseAsHex(): ByteArray = BaseEncoding.base16().decode(this)

View File

@ -26,10 +26,6 @@ fun makeNoWhitelistClassResolver(): ClassResolver {
} }
class CordaClassResolver(val whitelist: ClassWhitelist) : DefaultClassResolver() { class CordaClassResolver(val whitelist: ClassWhitelist) : DefaultClassResolver() {
companion object {
private val logger = loggerFor<CordaClassResolver>()
}
/** Returns the registration for the specified class, or null if the class is not registered. */ /** Returns the registration for the specified class, or null if the class is not registered. */
override fun getRegistration(type: Class<*>): Registration? { override fun getRegistration(type: Class<*>): Registration? {
return super.getRegistration(type) ?: checkClass(type) return super.getRegistration(type) ?: checkClass(type)
@ -147,10 +143,14 @@ class GlobalTransientClassWhiteList(val delegate: ClassWhitelist) : MutableClass
} }
} }
/** /**
* This class is not currently used, but can be installed to log a large number of missing entries from the whitelist * This class is not currently used, but can be installed to log a large number of missing entries from the whitelist
* and was used to track down the initial set. * and was used to track down the initial set.
*
* @suppress
*/ */
@Suppress("unused")
class LoggingWhitelist(val delegate: ClassWhitelist, val global: Boolean = true) : MutableClassWhitelist { class LoggingWhitelist(val delegate: ClassWhitelist, val global: Boolean = true) : MutableClassWhitelist {
companion object { companion object {
val log = loggerFor<LoggingWhitelist>() val log = loggerFor<LoggingWhitelist>()
@ -178,9 +178,7 @@ class LoggingWhitelist(val delegate: ClassWhitelist, val global: Boolean = true)
alreadySeen += type.name alreadySeen += type.name
val className = Util.className(type) val className = Util.className(type)
log.warn("Dynamically whitelisted class $className") log.warn("Dynamically whitelisted class $className")
if (journalWriter != null) { journalWriter?.println(className)
journalWriter.println(className)
}
} }
return true return true
} }

View File

@ -72,10 +72,12 @@ fun p2PKryo(): KryoPool = kryoPool
// Same again, but this has whitelisting turned off for internal storage use only. // Same again, but this has whitelisting turned off for internal storage use only.
fun storageKryo(): KryoPool = internalKryoPool fun storageKryo(): KryoPool = internalKryoPool
/** /**
* A type safe wrapper around a byte array that contains a serialised object. You can call [SerializedBytes.deserialize] * A type safe wrapper around a byte array that contains a serialised object. You can call [SerializedBytes.deserialize]
* to get the original object back. * to get the original object back.
*/ */
@Suppress("unused") // Type parameter is just for documentation purposes.
class SerializedBytes<T : Any>(bytes: ByteArray, val internalOnly: Boolean = false) : OpaqueBytes(bytes) { class SerializedBytes<T : Any>(bytes: ByteArray, val internalOnly: Boolean = false) : OpaqueBytes(bytes) {
// It's OK to use lazy here because SerializedBytes is configured to use the ImmutableClassSerializer. // It's OK to use lazy here because SerializedBytes is configured to use the ImmutableClassSerializer.
val hash: SecureHash by lazy { bytes.sha256() } val hash: SecureHash by lazy { bytes.sha256() }
@ -542,25 +544,6 @@ fun <T> Kryo.withAttachmentStorage(attachmentStorage: AttachmentStorage?, block:
} }
} }
object OrderedSerializer : Serializer<HashMap<Any, Any>>() {
override fun write(kryo: Kryo, output: Output, obj: HashMap<Any, Any>) {
//Change a HashMap to LinkedHashMap.
val linkedMap = LinkedHashMap<Any, Any>()
val sorted = obj.toList().sortedBy { it.first.hashCode() }
for ((k, v) in sorted) {
linkedMap.put(k, v)
}
kryo.writeClassAndObject(output, linkedMap)
}
//It will be deserialized as a LinkedHashMap.
@Suppress("UNCHECKED_CAST")
override fun read(kryo: Kryo, input: Input, type: Class<HashMap<Any, Any>>): HashMap<Any, Any> {
val hm = kryo.readClassAndObject(input) as HashMap<Any, Any>
return hm
}
}
/** For serialising a MetaData object. */ /** For serialising a MetaData object. */
@ThreadSafe @ThreadSafe
object MetaDataSerializer : Serializer<MetaData>() { object MetaDataSerializer : Serializer<MetaData>() {

View File

@ -103,7 +103,6 @@ class SerializeAsTokenContext(toBeTokenized: Any, kryoPool: KryoPool) {
*/ */
@CordaSerializable @CordaSerializable
data class SingletonSerializationToken private constructor(private val className: String) : SerializationToken { data class SingletonSerializationToken private constructor(private val className: String) : SerializationToken {
constructor(toBeTokenized: SerializeAsToken) : this(toBeTokenized.javaClass.name) constructor(toBeTokenized: SerializeAsToken) : this(toBeTokenized.javaClass.name)
override fun fromToken(context: SerializeAsTokenContext): Any = context.tokenToTokenized[this] ?: override fun fromToken(context: SerializeAsTokenContext): Any = context.tokenToTokenized[this] ?:

View File

@ -147,7 +147,7 @@ open class TransactionBuilder(
open fun addInputState(stateAndRef: StateAndRef<*>) { open fun addInputState(stateAndRef: StateAndRef<*>) {
check(currentSigs.isEmpty()) check(currentSigs.isEmpty())
val notary = stateAndRef.state.notary val notary = stateAndRef.state.notary
require(notary == this.notary) { "Input state requires notary \"${notary}\" which does not match the transaction notary \"${this.notary}\"." } require(notary == this.notary) { "Input state requires notary \"$notary\" which does not match the transaction notary \"${this.notary}\"." }
signers.add(notary.owningKey) signers.add(notary.owningKey)
inputs.add(stateAndRef.ref) inputs.add(stateAndRef.ref)
} }

View File

@ -1,31 +0,0 @@
package net.corda.core.utilities
import net.corda.core.ErrorOr
import net.corda.core.crypto.Party
import net.corda.core.crypto.parsePublicKeyBase58
import net.corda.core.messaging.CordaRPCOps
import javax.ws.rs.core.Response
/**
* Utility functions to reduce boilerplate when developing HTTP APIs
*/
class ApiUtils(val rpc: CordaRPCOps) {
private val defaultNotFound = { msg: String -> Response.status(Response.Status.NOT_FOUND).entity(msg).build() }
/**
* Get a party and then execute the passed function with the party public key as a parameter.
* Usage: withParty(key) { doSomethingWith(it) }
*/
fun withParty(partyKeyStr: String, notFound: (String) -> Response = defaultNotFound, found: (Party) -> Response): Response {
val party = try {
val partyKey = parsePublicKeyBase58(partyKeyStr)
ErrorOr(rpc.partyFromKey(partyKey))
} catch (e: IllegalArgumentException) {
ErrorOr.of(Exception("Invalid base58 key passed for party key $e"))
}
return party.bind { if (it == null) ErrorOr.of(Exception("Unknown party")) else ErrorOr(found(it)) }.match(
onValue = { it },
onError = { notFound(it.toString()) }
)
}
}

View File

@ -57,20 +57,6 @@ class ProgressTracker(vararg steps: Step) {
open fun childProgressTracker(): ProgressTracker? = null open fun childProgressTracker(): ProgressTracker? = null
} }
// TODO: There's no actual way to create these steps anymore!
/** This class makes it easier to relabel a step on the fly, to provide transient information. */
open inner class RelabelableStep(currentLabel: String) : Step(currentLabel) {
override val changes: BehaviorSubject<Change> = BehaviorSubject.create()
var currentLabel: String = currentLabel
set(value) {
field = value
changes.onNext(ProgressTracker.Change.Rendering(this@ProgressTracker, this@RelabelableStep))
}
override val label: String get() = currentLabel
}
// Sentinel objects. Overrides equals() to survive process restarts and serialization. // Sentinel objects. Overrides equals() to survive process restarts and serialization.
object UNSTARTED : Step("Unstarted") { object UNSTARTED : Step("Unstarted") {
override fun equals(other: Any?) = other is UNSTARTED override fun equals(other: Any?) = other is UNSTARTED

View File

@ -31,17 +31,6 @@ import java.security.PublicKey
* *
*/ */
object TwoPartyDealFlow { object TwoPartyDealFlow {
@CordaSerializable
class DealMismatchException(val expectedDeal: ContractState, val actualDeal: ContractState) : Exception() {
override fun toString() = "The submitted deal didn't match the expected: $expectedDeal vs $actualDeal"
}
@CordaSerializable
class DealRefMismatchException(val expectedDeal: StateRef, val actualDeal: StateRef) : Exception() {
override fun toString() = "The submitted deal didn't match the expected: $expectedDeal vs $actualDeal"
}
// This object is serialised to the network and is the first flow message the seller sends to the buyer. // This object is serialised to the network and is the first flow message the seller sends to the buyer.
@CordaSerializable @CordaSerializable
data class Handshake<out T>(val payload: T, val publicKey: PublicKey) data class Handshake<out T>(val payload: T, val publicKey: PublicKey)

View File

@ -19,7 +19,7 @@ class FinanceTypesTest {
@Test @Test
fun `valid tenor tests`() { fun `valid tenor tests`() {
val exampleTenors = ("ON,1D,2D,3D,4D,5D,6D,7D,1W,2W,3W,1M,3M,6M,1Y,2Y,3Y,5Y,10Y,12Y,20Y").split(",") val exampleTenors = ("ON,1D,2D,3D,4D,5D,6D,7D,1W,2W,3W,1M,3M,6M,1Y,2Y,3Y,5Y,10Y,12Y,20Y").split(",")
exampleTenors.all { Tenor(it).name.length > 0 } // Slightly obtuse way of ensuring no exception thrown in construction. exampleTenors.all { Tenor(it).name.isNotEmpty() } // Slightly obtuse way of ensuring no exception thrown in construction.
} }
@Test @Test

View File

@ -23,8 +23,8 @@ class TransactionEncumbranceTests {
) )
val stateWithNewOwner = state.copy(owner = DUMMY_PUBKEY_2) val stateWithNewOwner = state.copy(owner = DUMMY_PUBKEY_2)
val FOUR_PM = Instant.parse("2015-04-17T16:00:00.00Z") val FOUR_PM: Instant = Instant.parse("2015-04-17T16:00:00.00Z")
val FIVE_PM = FOUR_PM.plus(1, ChronoUnit.HOURS) val FIVE_PM: Instant = FOUR_PM.plus(1, ChronoUnit.HOURS)
val timeLock = DummyTimeLock.State(FIVE_PM) val timeLock = DummyTimeLock.State(FIVE_PM)
class DummyTimeLock : Contract { class DummyTimeLock : Contract {

View File

@ -51,7 +51,7 @@ object TxKeyFlow {
@Suspendable @Suspendable
override fun call(): PublicKey { override fun call(): PublicKey {
progressTracker.currentStep == SENDING_KEY progressTracker.currentStep = SENDING_KEY
return TxKeyFlowUtilities.provideKey(this, otherSide) return TxKeyFlowUtilities.provideKey(this, otherSide)
} }
} }

View File

@ -16,6 +16,7 @@ import org.junit.Before
import org.junit.Test import org.junit.Test
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.net.URL
import java.net.URLClassLoader import java.net.URLClassLoader
import java.security.PublicKey import java.security.PublicKey
import java.util.jar.JarOutputStream import java.util.jar.JarOutputStream
@ -33,7 +34,7 @@ val ATTACHMENT_TEST_PROGRAM_ID = AttachmentClassLoaderTests.AttachmentDummyContr
class AttachmentClassLoaderTests { class AttachmentClassLoaderTests {
companion object { companion object {
val ISOLATED_CONTRACTS_JAR_PATH = AttachmentClassLoaderTests::class.java.getResource("isolated.jar") val ISOLATED_CONTRACTS_JAR_PATH: URL = AttachmentClassLoaderTests::class.java.getResource("isolated.jar")
} }
class AttachmentDummyContract : Contract { class AttachmentDummyContract : Contract {

View File

@ -31,7 +31,7 @@ class DBTransactionMappingStorage : StateMachineRecordedTransactionMappingStorag
private class TransactionMappingsMap : AbstractJDBCHashMap<SecureHash, StateMachineRunId, Table>(Table, loadOnInit = false) { private class TransactionMappingsMap : AbstractJDBCHashMap<SecureHash, StateMachineRunId, Table>(Table, loadOnInit = false) {
override fun keyFromRow(row: ResultRow): SecureHash = row[table.txId] override fun keyFromRow(row: ResultRow): SecureHash = row[table.txId]
override fun valueFromRow(row: ResultRow): StateMachineRunId = StateMachineRunId.wrap(row[table.stateMachineRunId]) override fun valueFromRow(row: ResultRow): StateMachineRunId = StateMachineRunId(row[table.stateMachineRunId])
override fun addKeyToInsert(insert: InsertStatement, entry: Map.Entry<SecureHash, StateMachineRunId>, finalizables: MutableList<() -> Unit>) { override fun addKeyToInsert(insert: InsertStatement, entry: Map.Entry<SecureHash, StateMachineRunId>, finalizables: MutableList<() -> Unit>) {
insert[table.txId] = entry.key insert[table.txId] = entry.key