From eb3f8186189468305cbd8400e460fda8c4889ad6 Mon Sep 17 00:00:00 2001 From: Matthew Layton Date: Tue, 16 Feb 2021 14:52:19 +0000 Subject: [PATCH 1/6] Added signed command implementation and tests. --- CHANGELOG.md | 3 ++ .../corda/core/contract/ContractID.kt | 12 ++++++ .../corda/core/contract/DummyContract.kt | 43 +++++++++++++++---- .../corda/core/contract/SignedCommandData.kt | 26 +++++++++++ .../core/contract/VerifiedCommandData.kt | 19 ++++++++ .../corda/core/contract/ContractTest.kt | 30 +++++++++++++ .../contract/DummyContractCommandTests.kt | 22 ++++++++++ .../corda/core/contract/DummyContractTests.kt | 20 +++++++++ .../onixlabs/corda/core/contract/MockData.kt | 4 +- 9 files changed, 170 insertions(+), 9 deletions(-) create mode 100644 onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/ContractID.kt create mode 100644 onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/SignedCommandData.kt create mode 100644 onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/VerifiedCommandData.kt create mode 100644 onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/ContractTest.kt create mode 100644 onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/DummyContractCommandTests.kt create mode 100644 onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/DummyContractTests.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fe28ca..8c8eb77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,9 @@ This document serves as the change log for the ONIXLabs Corda Core API. - Moved to new extension file naming convention for maintainability. - Added extensions to obtain single inputs, reference inputs and outputs from a `LedgerTransaction`. - Added extension to cast `Iterable>` to `List>`. +- Added `ContractID` interface which automatically binds a contract ID to a contract class. +- Added `SignedCommandData` interface which defines a contract command that must include a signature. +- Added `VerifiedCommandData` interface which verifies a ledger transaction. ### Workflow diff --git a/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/ContractID.kt b/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/ContractID.kt new file mode 100644 index 0000000..000ce97 --- /dev/null +++ b/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/ContractID.kt @@ -0,0 +1,12 @@ +package io.onixlabs.corda.core.contract + +import net.corda.core.contracts.ContractClassName + +/** + * Defines an interface which automatically binds a contract ID to a contract class. + * + * @property ID The ID of the contract. + */ +interface ContractID { + val ID: ContractClassName get() = this::class.java.enclosingClass.canonicalName +} diff --git a/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/DummyContract.kt b/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/DummyContract.kt index 4432a1c..b4a7b13 100644 --- a/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/DummyContract.kt +++ b/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/DummyContract.kt @@ -16,23 +16,50 @@ package io.onixlabs.corda.core.contract -import net.corda.core.contracts.BelongsToContract -import net.corda.core.contracts.Contract -import net.corda.core.contracts.StateRef +import net.corda.core.contracts.* +import net.corda.core.crypto.DigitalSignature import net.corda.core.identity.AbstractParty import net.corda.core.transactions.LedgerTransaction +import java.security.PublicKey /** * Represents a dummy state and contract that will never be used. - * This exists so that Corda will load the contract into attachment storage. + * This exists for two reasons: + * 1. So that Corda will load the contract into attachment storage. + * 2. To test contract interface implementations locally. */ @Suppress("UNUSED") internal class DummyContract : Contract { - override fun verify(tx: LedgerTransaction) = Unit + + companion object : ContractID @BelongsToContract(DummyContract::class) - class DummyState : ChainState { - override val previousStateRef: StateRef? get() = null - override val participants: List get() = emptyList() + data class DummyState( + override val participants: List = emptyList(), + override val previousStateRef: StateRef? = null + ) : ChainState + + override fun verify(tx: LedgerTransaction) { + val command = tx.commands.requireSingleCommand() + when (command.value) { + is DummyCommand -> command.value.verify(tx, command.signers.toSet()) + else -> throw IllegalArgumentException("Unrecognised command: ${command.value}.") + } + } + + interface DummyContractCommand : SignedCommandData, VerifiedCommandData + + class DummyCommand(override val signature: DigitalSignature) : DummyContractCommand { + + companion object { + internal const val CONTRACT_RULE_STATES_WERE_SIGNED = + "On dummy command, the dummy state must be signed by the state participant." + } + + override fun verify(transaction: LedgerTransaction, signers: Set) = requireThat { + val state = transaction.singleOutputOfType() + val hash = state.hash() + CONTRACT_RULE_STATES_WERE_SIGNED using isSignedBy(hash.bytes, state.participants.single().owningKey) + } } } diff --git a/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/SignedCommandData.kt b/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/SignedCommandData.kt new file mode 100644 index 0000000..8a54757 --- /dev/null +++ b/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/SignedCommandData.kt @@ -0,0 +1,26 @@ +package io.onixlabs.corda.core.contract + +import net.corda.core.contracts.CommandData +import net.corda.core.crypto.DigitalSignature +import net.corda.core.crypto.isValid +import java.security.PublicKey + +/** + * Defines a contract command that must include a signature. + * + * @property signature The signature to include as a payload in the command. + */ +interface SignedCommandData : CommandData { + val signature: DigitalSignature + + /** + * Verifies that the signature correlates with the specified content and signing key. + * + * @param content The unsigned content to verify against the signature. + * @param publicKey The public key which was used to sign the content. + * @return Returns true if the content and public key correlate with the signature; otherwise, false. + */ + fun isSignedBy(content: ByteArray, publicKey: PublicKey): Boolean { + return publicKey.isValid(content, signature) + } +} diff --git a/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/VerifiedCommandData.kt b/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/VerifiedCommandData.kt new file mode 100644 index 0000000..05aef5d --- /dev/null +++ b/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/VerifiedCommandData.kt @@ -0,0 +1,19 @@ +package io.onixlabs.corda.core.contract + +import net.corda.core.contracts.CommandData +import net.corda.core.transactions.LedgerTransaction +import java.security.PublicKey + +/** + * Defines a contract command that can verify a ledger transaction. + */ +interface VerifiedCommandData : CommandData { + + /** + * Verifies a ledger transaction. + * + * @param transaction The ledger transaction to verify. + * @param signers The list of signers expected to sign the transaction. + */ + fun verify(transaction: LedgerTransaction, signers: Set) +} diff --git a/onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/ContractTest.kt b/onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/ContractTest.kt new file mode 100644 index 0000000..5dc0b5d --- /dev/null +++ b/onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/ContractTest.kt @@ -0,0 +1,30 @@ +package io.onixlabs.corda.core.contract + +import net.corda.core.node.NotaryInfo +import net.corda.testing.common.internal.testNetworkParameters +import net.corda.testing.core.TestIdentity +import net.corda.testing.node.MockServices +import org.junit.jupiter.api.BeforeEach + +abstract class ContractTest { + + protected companion object { + private val cordapps = listOf("io.onixlabs.corda.core.contract") + private val contracts = listOf(DummyContract.ID) + + fun keysOf(vararg identities: TestIdentity) = identities.map { it.publicKey } + } + + private lateinit var _services: MockServices + protected val services: MockServices get() = _services + + @BeforeEach + private fun setup() { + val networkParameters = testNetworkParameters( + minimumPlatformVersion = 8, + notaries = listOf(NotaryInfo(NOTARY.party, true)) + ) + _services = MockServices(cordapps, IDENTITY_A, networkParameters, IDENTITY_B, IDENTITY_C) + contracts.forEach { _services.addMockCordapp(it) } + } +} diff --git a/onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/DummyContractCommandTests.kt b/onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/DummyContractCommandTests.kt new file mode 100644 index 0000000..61a73cd --- /dev/null +++ b/onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/DummyContractCommandTests.kt @@ -0,0 +1,22 @@ +package io.onixlabs.corda.core.contract + +import net.corda.core.contracts.hash +import net.corda.core.crypto.sign +import net.corda.testing.node.ledger +import org.junit.jupiter.api.Test + +class DummyContractCommandTests : ContractTest() { + + @Test + fun `On dummy command, the dummy state must be signed by the state participant`() { + services.ledger { + transaction { + val state = DummyContract.DummyState(listOf(IDENTITY_A.party)) + val signature = IDENTITY_B.keyPair.private.sign(state.hash().bytes) + output(DummyContract.ID, state) + command(keysOf(IDENTITY_A), DummyContract.DummyCommand(signature)) + failsWith(DummyContract.DummyCommand.CONTRACT_RULE_STATES_WERE_SIGNED) + } + } + } +} diff --git a/onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/DummyContractTests.kt b/onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/DummyContractTests.kt new file mode 100644 index 0000000..b684590 --- /dev/null +++ b/onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/DummyContractTests.kt @@ -0,0 +1,20 @@ +package io.onixlabs.corda.core.contract + +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +class DummyContractTests { + + @Test + fun `DummyContract ID should be the canonical name of the DummyContract class`() { + + // Arrange + val expected = "io.onixlabs.corda.core.contract.DummyContract" + + // Act + val actual = DummyContract.ID + + // Assert + assertEquals(expected, actual) + } +} diff --git a/onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/MockData.kt b/onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/MockData.kt index ecd0f0d..40f6598 100644 --- a/onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/MockData.kt +++ b/onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/MockData.kt @@ -1,8 +1,10 @@ package io.onixlabs.corda.core.contract import net.corda.core.identity.CordaX500Name +import net.corda.testing.core.DUMMY_NOTARY_NAME import net.corda.testing.core.TestIdentity val IDENTITY_A = TestIdentity(CordaX500Name("PartyA", "London", "GB")) val IDENTITY_B = TestIdentity(CordaX500Name("PartyB", "New York", "US")) -val IDENTITY_C = TestIdentity(CordaX500Name("PartyC", "Paris", "FR")) \ No newline at end of file +val IDENTITY_C = TestIdentity(CordaX500Name("PartyC", "Paris", "FR")) +val NOTARY = TestIdentity(DUMMY_NOTARY_NAME) From e27960b608bf8a38ab611fe4466e6e86ab707980 Mon Sep 17 00:00:00 2001 From: Matthew Layton Date: Wed, 17 Feb 2021 19:02:14 +0000 Subject: [PATCH 2/6] Update command signature implementation. --- CHANGELOG.md | 1 + build.gradle | 2 +- .../corda/core/contract/DummyContract.kt | 15 ++-- .../corda/core/contract/SignatureData.kt | 74 +++++++++++++++++++ .../corda/core/contract/SignedCommandData.kt | 16 +--- .../contract/DummyContractCommandTests.kt | 8 +- 6 files changed, 90 insertions(+), 26 deletions(-) create mode 100644 onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/SignatureData.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c8eb77..89bcba4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ This document serves as the change log for the ONIXLabs Corda Core API. - Added `ContractID` interface which automatically binds a contract ID to a contract class. - Added `SignedCommandData` interface which defines a contract command that must include a signature. - Added `VerifiedCommandData` interface which verifies a ledger transaction. +- Added `SignatureData` class, which represents a digital signature, and it's unsigned counterpart. ### Workflow diff --git a/build.gradle b/build.gradle index 4d1b5c3..825ca39 100644 --- a/build.gradle +++ b/build.gradle @@ -42,7 +42,7 @@ buildscript { } group 'io.onixlabs' -version '1.1.0' +version '1.2.0' subprojects { repositories { diff --git a/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/DummyContract.kt b/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/DummyContract.kt index b4a7b13..ac664ff 100644 --- a/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/DummyContract.kt +++ b/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/DummyContract.kt @@ -17,7 +17,6 @@ package io.onixlabs.corda.core.contract import net.corda.core.contracts.* -import net.corda.core.crypto.DigitalSignature import net.corda.core.identity.AbstractParty import net.corda.core.transactions.LedgerTransaction import java.security.PublicKey @@ -49,17 +48,21 @@ internal class DummyContract : Contract { interface DummyContractCommand : SignedCommandData, VerifiedCommandData - class DummyCommand(override val signature: DigitalSignature) : DummyContractCommand { + class DummyCommand(override val signature: SignatureData) : DummyContractCommand { companion object { - internal const val CONTRACT_RULE_STATES_WERE_SIGNED = - "On dummy command, the dummy state must be signed by the state participant." + internal const val CONTRACT_RULE_COMMAND_SIGNED = + "On dummy command, the command must be signed by the dummy state participant." } override fun verify(transaction: LedgerTransaction, signers: Set) = requireThat { val state = transaction.singleOutputOfType() - val hash = state.hash() - CONTRACT_RULE_STATES_WERE_SIGNED using isSignedBy(hash.bytes, state.participants.single().owningKey) + val command = transaction.singleCommandOfType() + + val key = state.participants.single().owningKey + val signature = command.value.signature + + CONTRACT_RULE_COMMAND_SIGNED using (signature.verify(key)) } } } diff --git a/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/SignatureData.kt b/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/SignatureData.kt new file mode 100644 index 0000000..572ef0f --- /dev/null +++ b/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/SignatureData.kt @@ -0,0 +1,74 @@ +package io.onixlabs.corda.core.contract + +import net.corda.core.crypto.Crypto +import net.corda.core.crypto.DigitalSignature +import net.corda.core.crypto.sign +import net.corda.core.node.ServiceHub +import net.corda.core.serialization.CordaSerializable +import net.corda.core.utilities.toBase64 +import java.security.PrivateKey +import java.security.PublicKey +import java.util.* + +/** + * Represents an array of unsigned bytes, and its signed equivalent. + * + * @property content The unsigned signature content. + * @property signature The digital signature representing the signed content. + */ +@CordaSerializable +data class SignatureData(private val content: ByteArray, private val signature: DigitalSignature) { + + companion object { + fun create(content: ByteArray, privateKey: PrivateKey): SignatureData { + val signature = privateKey.sign(content) + return SignatureData(content, signature) + } + + fun create(content: ByteArray, publicKey: PublicKey, serviceHub: ServiceHub): SignatureData { + val signature = serviceHub.keyManagementService.sign(content, publicKey) + return SignatureData(content, signature.withoutKey()) + } + } + + /** + * Verifies the signature data using the specified public key. + * + * @param publicKey The public key to verify against the signature. + * @return Returns true if the public key was used to sign the data; otherwise, false. + */ + fun verify(publicKey: PublicKey): Boolean { + return Crypto.isValid(publicKey, signature.bytes, content) + } + + /** + * Determines whether the specified object is equal to the current object. + * + * @param other The object to compare with the current object. + * @return Returns true if the specified object is equal to the current object; otherwise, false. + */ + override fun equals(other: Any?): Boolean { + return this === other || (other is SignatureData + && content.contentEquals(other.content) + && signature == other.signature) + } + + /** + * Serves as the default hash function. + * + * @return Returns a hash code for the current object. + */ + override fun hashCode(): Int { + return Objects.hash(signature, content.contentHashCode()) + } + + /** + * Returns a string that represents the current object. + * + * @return Returns a string that represents the current object. + */ + override fun toString(): String = buildString { + appendln("Unsigned bytes: ${content.toBase64()}") + appendln("Signed bytes: ${signature.bytes.toBase64()}") + } +} diff --git a/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/SignedCommandData.kt b/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/SignedCommandData.kt index 8a54757..4ef52b4 100644 --- a/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/SignedCommandData.kt +++ b/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/SignedCommandData.kt @@ -1,9 +1,6 @@ package io.onixlabs.corda.core.contract import net.corda.core.contracts.CommandData -import net.corda.core.crypto.DigitalSignature -import net.corda.core.crypto.isValid -import java.security.PublicKey /** * Defines a contract command that must include a signature. @@ -11,16 +8,5 @@ import java.security.PublicKey * @property signature The signature to include as a payload in the command. */ interface SignedCommandData : CommandData { - val signature: DigitalSignature - - /** - * Verifies that the signature correlates with the specified content and signing key. - * - * @param content The unsigned content to verify against the signature. - * @param publicKey The public key which was used to sign the content. - * @return Returns true if the content and public key correlate with the signature; otherwise, false. - */ - fun isSignedBy(content: ByteArray, publicKey: PublicKey): Boolean { - return publicKey.isValid(content, signature) - } + val signature: SignatureData } diff --git a/onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/DummyContractCommandTests.kt b/onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/DummyContractCommandTests.kt index 61a73cd..ed066cc 100644 --- a/onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/DummyContractCommandTests.kt +++ b/onixlabs-corda-core-contract/src/test/kotlin/io/onixlabs/corda/core/contract/DummyContractCommandTests.kt @@ -1,7 +1,6 @@ package io.onixlabs.corda.core.contract -import net.corda.core.contracts.hash -import net.corda.core.crypto.sign +import net.corda.core.crypto.SecureHash import net.corda.testing.node.ledger import org.junit.jupiter.api.Test @@ -12,10 +11,11 @@ class DummyContractCommandTests : ContractTest() { services.ledger { transaction { val state = DummyContract.DummyState(listOf(IDENTITY_A.party)) - val signature = IDENTITY_B.keyPair.private.sign(state.hash().bytes) + val content = SecureHash.randomSHA256().bytes + val signature = SignatureData.create(content, IDENTITY_B.keyPair.private) output(DummyContract.ID, state) command(keysOf(IDENTITY_A), DummyContract.DummyCommand(signature)) - failsWith(DummyContract.DummyCommand.CONTRACT_RULE_STATES_WERE_SIGNED) + failsWith(DummyContract.DummyCommand.CONTRACT_RULE_COMMAND_SIGNED) } } } From 8b5882a7d69d04a4b07fe5dd11414db9a7de9dff Mon Sep 17 00:00:00 2001 From: Matthew Layton Date: Wed, 17 Feb 2021 19:57:15 +0000 Subject: [PATCH 3/6] Added format cast extensions for Java. --- .../core/contract/Extensions.StateAndRef.kt | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/Extensions.StateAndRef.kt b/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/Extensions.StateAndRef.kt index 9ab6394..3b762c8 100644 --- a/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/Extensions.StateAndRef.kt +++ b/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/Extensions.StateAndRef.kt @@ -24,11 +24,35 @@ import net.corda.core.contracts.TransactionState * Casts a [StateAndRef] of an unknown [ContractState] to a [StateAndRef] of type [T]. * * @param T The underlying [ContractState] type to cast to. + * @param contractStateClass The [ContractState] class to cast to. * @return Returns a [StateAndRef] of type [T]. * @throws ClassCastException if the unknown [ContractState] type cannot be cast to [T]. */ -inline fun StateAndRef<*>.cast(): StateAndRef where T : ContractState = with(state) { - StateAndRef(TransactionState(T::class.java.cast(data), contract, notary, encumbrance, constraint), ref) +fun StateAndRef<*>.cast(contractStateClass: Class): StateAndRef where T : ContractState = with(state) { + StateAndRef(TransactionState(contractStateClass.cast(data), contract, notary, encumbrance, constraint), ref) +} + +/** + * Casts a [StateAndRef] of an unknown [ContractState] to a [StateAndRef] of type [T]. + * + * @param T The underlying [ContractState] type to cast to. + * @return Returns a [StateAndRef] of type [T]. + * @throws ClassCastException if the unknown [ContractState] type cannot be cast to [T]. + */ +inline fun StateAndRef<*>.cast(): StateAndRef where T : ContractState { + return cast(T::class.java) +} + +/** + * Casts an iterable of [StateAndRef] of an unknown [ContractState] to a list of [StateAndRef] of type [T]. + * + * @param T The underlying [ContractState] type to cast to. + * @param contractStateClass The [ContractState] class to cast to. + * @return Returns a list of [StateAndRef] of type [T]. + * @throws ClassCastException if the unknown [ContractState] type cannot be cast to [T]. + */ +fun Iterable>.cast(contractStateClass: Class): List> where T : ContractState { + return map { it.cast(contractStateClass) } } /** @@ -39,5 +63,5 @@ inline fun StateAndRef<*>.cast(): StateAndRef where T : ContractS * @throws ClassCastException if the unknown [ContractState] type cannot be cast to [T]. */ inline fun Iterable>.cast(): List> where T : ContractState { - return map { it.cast() } + return cast(T::class.java) } From a8e004481ac586de0dadd1964bab6c12742b8919 Mon Sep 17 00:00:00 2001 From: Matthew Layton Date: Thu, 18 Feb 2021 15:49:57 +0000 Subject: [PATCH 4/6] Removing cleanLocal to preserve old versions. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 825ca39..26cb2f5 100644 --- a/build.gradle +++ b/build.gradle @@ -93,10 +93,10 @@ task cleanLocal(type: Exec) { task releaseLocal(type: GradleBuild) { startParameter = gradle.startParameter.newInstance() - tasks = ['cleanLocal', 'clean', 'build', 'publishToMavenLocal'] + tasks = ['clean', 'build', 'publishToMavenLocal'] } task releasePublic(type: GradleBuild) { startParameter = gradle.startParameter.newInstance() - tasks = ['cleanLocal', 'clean', 'build', 'publishToMavenLocal', 'publish'] + tasks = ['clean', 'build', 'publishToMavenLocal', 'publish'] } From bba85d2eadcc6ea7822415e3e82eaac5fbe295f8 Mon Sep 17 00:00:00 2001 From: Matthew Layton Date: Thu, 18 Feb 2021 16:48:08 +0000 Subject: [PATCH 5/6] Removing cleanLocal to preserve old versions. --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 4d1b5c3..612ae7c 100644 --- a/build.gradle +++ b/build.gradle @@ -93,10 +93,10 @@ task cleanLocal(type: Exec) { task releaseLocal(type: GradleBuild) { startParameter = gradle.startParameter.newInstance() - tasks = ['cleanLocal', 'clean', 'build', 'publishToMavenLocal'] + tasks = ['clean', 'build', 'publishToMavenLocal'] } task releasePublic(type: GradleBuild) { startParameter = gradle.startParameter.newInstance() - tasks = ['cleanLocal', 'clean', 'build', 'publishToMavenLocal', 'publish'] + tasks = ['clean', 'build', 'publishToMavenLocal', 'publish'] } From 16398e6ae467baaff4d785c11474f764f42e1a69 Mon Sep 17 00:00:00 2001 From: Matthew Layton Date: Fri, 19 Feb 2021 11:32:33 +0000 Subject: [PATCH 6/6] documentation. --- .../corda/core/contract/SignatureData.kt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/SignatureData.kt b/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/SignatureData.kt index 572ef0f..b725c84 100644 --- a/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/SignatureData.kt +++ b/onixlabs-corda-core-contract/src/main/kotlin/io/onixlabs/corda/core/contract/SignatureData.kt @@ -20,11 +20,27 @@ import java.util.* data class SignatureData(private val content: ByteArray, private val signature: DigitalSignature) { companion object { + + /** + * Creates a signature from the specified content and private key. + * + * @param content The content to sign. + * @param privateKey The private key to sign the content. + * @return Returns a new signature containing the content and signed data. + */ fun create(content: ByteArray, privateKey: PrivateKey): SignatureData { val signature = privateKey.sign(content) return SignatureData(content, signature) } + /** + * Creates a signature from the specified content by resolving the signing key from the service hub. + * + * @param content The content to sign. + * @param publicKey The public key to resolve from the service hub. + * @param serviceHub The service hub to resolve the public key. + * @return Returns a new signature containing the content and signed data. + */ fun create(content: ByteArray, publicKey: PublicKey, serviceHub: ServiceHub): SignatureData { val signature = serviceHub.keyManagementService.sign(content, publicKey) return SignatureData(content, signature.withoutKey())