From e4a0bc6e116d258f218a9d71544e30c1da7de47a Mon Sep 17 00:00:00 2001 From: Ross Nicoll Date: Wed, 10 May 2017 11:55:52 +0100 Subject: [PATCH] Move party classes into identity package Move AbstractParty, AnonymousParty and Party into a new net.corda.core.identity package, as they're not really cryptography tools, and in preparation for further code coming in for identity. Optimize imports on many files to clean up the resulting refactor. --- .../net/corda/jackson/JacksonSupport.kt | 2 + .../net/corda/client/mock/EventGenerator.kt | 2 +- .../net/corda/core/contracts/ContractsDSL.kt | 2 +- .../net/corda/core/contracts/DummyContract.kt | 2 +- .../net/corda/core/contracts/FungibleAsset.kt | 2 +- .../net/corda/core/contracts/Structures.kt | 4 +- .../corda/core/contracts/TransactionTypes.kt | 2 +- .../core/contracts/TransactionVerification.kt | 2 +- .../net/corda/core/crypto/CryptoUtils.kt | 1 + .../net/corda/core/crypto/DigitalSignature.kt | 1 + .../kotlin/net/corda/core/crypto/Party.kt | 30 +-------------- .../kotlin/net/corda/core/flows/FlowLogic.kt | 2 +- .../net/corda/core/flows/FlowStateMachine.kt | 2 +- .../{crypto => identity}/AbstractParty.kt | 2 +- .../{crypto => identity}/AnonymousParty.kt | 3 +- .../kotlin/net/corda/core/identity/Party.kt | 35 ++++++++++++++++++ .../net/corda/core/messaging/CordaRPCOps.kt | 2 +- .../kotlin/net/corda/core/node/NodeInfo.kt | 2 +- .../net/corda/core/node/PluginServiceHub.kt | 2 +- .../core/node/services/IdentityService.kt | 4 +- .../core/node/services/NetworkMapCache.kt | 2 +- .../net/corda/core/node/services/PartyInfo.kt | 2 +- .../net/corda/core/node/services/Services.kt | 2 + .../core/node/services/UniquenessProvider.kt | 2 +- .../net/corda/core/serialization/Kryo.kt | 1 + .../core/transactions/BaseTransaction.kt | 2 +- .../core/transactions/LedgerTransaction.kt | 2 +- .../core/transactions/MerkleTransaction.kt | 1 + .../core/transactions/TransactionBuilder.kt | 1 + .../core/transactions/WireTransaction.kt | 2 +- .../net/corda/core/utilities/TestConstants.kt | 1 + .../flows/AbstractStateReplacementFlow.kt | 1 + .../corda/flows/BroadcastTransactionFlow.kt | 2 +- .../net/corda/flows/FetchAttachmentsFlow.kt | 2 +- .../kotlin/net/corda/flows/FetchDataFlow.kt | 2 +- .../net/corda/flows/FetchTransactionsFlow.kt | 2 +- .../kotlin/net/corda/flows/FinalityFlow.kt | 2 +- .../net/corda/flows/NotaryChangeFlow.kt | 2 +- .../main/kotlin/net/corda/flows/NotaryFlow.kt | 1 + .../corda/flows/ResolveTransactionsFlow.kt | 2 +- .../net/corda/flows/TwoPartyDealFlow.kt | 2 + .../net/corda/flows/TxKeyFlowUtilities.kt | 2 +- .../net/corda/core/node/isolated.jar | Bin 7908 -> 8066 bytes .../net/corda/core/flows/FlowsInJavaTest.java | 2 +- .../corda/core/contracts/TransactionTests.kt | 9 +---- .../core/crypto/PartialMerkleTreeTest.kt | 1 + .../core/flows/ContractUpgradeFlowTest.kt | 2 +- .../core/flows/ResolveTransactionsFlowTest.kt | 2 +- .../kotlin/net/corda/core/flows/TxKeyFlow.kt | 2 +- .../core/flows/TxKeyFlowUtilitiesTests.kt | 2 +- .../core/{crypto => identity}/PartyTest.kt | 3 +- .../core/node/AttachmentClassLoaderTests.kt | 7 +++- .../AttachmentSerializationTest.kt | 2 +- .../net/corda/core/testing/Generators.kt | 2 + docs/source/changelog.rst | 13 +++++++ .../corda/docs/FxTransactionBuildTutorial.kt | 2 +- .../docs/WorkflowTransactionBuildTutorial.kt | 1 + docs/source/release-notes.rst | 3 ++ .../corda/contracts/universal/Arrangement.kt | 2 +- .../contracts/universal/ContractFunctions.kt | 2 +- .../net/corda/contracts/universal/Literal.kt | 2 +- .../corda/contracts/universal/Perceivable.kt | 2 +- .../corda/contracts/universal/PrettyPrint.kt | 2 +- .../contracts/universal/UniversalContract.kt | 2 +- .../net/corda/contracts/universal/Util.kt | 2 +- .../contracts/universal/ContractDefinition.kt | 5 ++- .../corda/contracts/AnotherDummyContract.kt | 2 +- .../corda/core/node/DummyContractBackdoor.kt | 2 +- .../corda/contracts/JavaCommercialPaper.java | 1 + .../net/corda/contracts/CommercialPaper.kt | 2 +- .../corda/contracts/CommercialPaperLegacy.kt | 2 +- .../kotlin/net/corda/contracts/asset/Cash.kt | 2 + .../contracts/asset/CommodityContract.kt | 2 +- .../net/corda/contracts/asset/Obligation.kt | 3 ++ .../contracts/testing/DummyDealContract.kt | 2 + .../corda/contracts/testing/VaultFiller.kt | 2 +- .../net/corda/flows/AbstractCashFlow.kt | 2 +- .../kotlin/net/corda/flows/CashExitFlow.kt | 2 +- .../kotlin/net/corda/flows/CashFlowCommand.kt | 2 +- .../kotlin/net/corda/flows/CashIssueFlow.kt | 2 +- .../kotlin/net/corda/flows/CashPaymentFlow.kt | 2 +- .../main/kotlin/net/corda/flows/IssuerFlow.kt | 2 +- .../net/corda/flows/TwoPartyTradeFlow.kt | 1 + .../AbstractStateReplacementFlowTest.java | 2 +- .../corda/contracts/CommercialPaperTests.kt | 3 +- .../net/corda/contracts/asset/CashTests.kt | 2 + .../net/corda/flows/CashExitFlowTests.kt | 2 +- .../net/corda/flows/CashIssueFlowTests.kt | 2 +- .../net/corda/flows/CashPaymentFlowTests.kt | 2 +- .../services/vault/schemas/VaultSchemaTest.kt | 1 + .../node/services/BFTNotaryServiceTests.kt | 2 +- .../node/services/DistributedServiceTests.kt | 2 +- .../node/services/RaftNotaryServiceTests.kt | 2 +- .../statemachine/FlowVersioningTest.kt | 2 +- .../services/messaging/MQSecurityTest.kt | 2 +- .../services/messaging/P2PSecurityTest.kt | 2 +- .../kotlin/net/corda/node/driver/Driver.kt | 2 +- .../net/corda/node/internal/AbstractNode.kt | 2 +- .../corda/node/services/CoreFlowHandlers.kt | 2 +- .../identity/InMemoryIdentityService.kt | 4 +- .../network/InMemoryNetworkMapCache.kt | 2 +- .../services/network/NetworkMapService.kt | 1 + .../network/PersistentNetworkMapService.kt | 2 +- .../node/services/statemachine/FlowSession.kt | 2 +- .../statemachine/FlowStateMachineImpl.kt | 2 +- .../services/statemachine/SessionMessage.kt | 2 +- .../statemachine/StateMachineManager.kt | 2 +- .../BFTNonValidatingNotaryService.kt | 2 +- .../node/services/transactions/BFTSMaRt.kt | 1 + .../InMemoryUniquenessProvider.kt | 2 +- .../transactions/NonValidatingNotaryFlow.kt | 2 +- .../services/transactions/NotaryService.kt | 2 +- .../PersistentUniquenessProvider.kt | 2 +- .../RaftNonValidatingNotaryService.kt | 2 +- .../transactions/RaftUniquenessProvider.kt | 2 +- .../RaftValidatingNotaryService.kt | 2 +- .../transactions/SimpleNotaryService.kt | 2 +- .../transactions/ValidatingNotaryFlow.kt | 2 +- .../transactions/ValidatingNotaryService.kt | 2 +- .../node/services/vault/NodeVaultService.kt | 2 + .../utilities/ServiceIdentityGenerator.kt | 2 +- .../net/corda/node/InteractiveShellTest.kt | 2 +- .../node/messaging/TwoPartyTradeFlowTests.kt | 4 +- .../node/services/MockServiceHubInternal.kt | 2 +- .../corda/node/services/NotaryChangeTests.kt | 2 +- .../services/events/ScheduledFlowTests.kt | 2 +- .../network/InMemoryIdentityServiceTests.kt | 2 +- .../persistence/DataVendingServiceTests.kt | 2 +- .../statemachine/FlowFrameworkTests.kt | 2 +- .../node/services/vault/VaultQueryTests.kt | 2 +- .../corda/attachmentdemo/AttachmentDemo.kt | 2 +- .../corda/bank/plugin/BankOfCordaPlugin.kt | 2 +- .../net/corda/irs/api/InterestRateSwapAPI.kt | 2 +- .../net/corda/irs/api/NodeInterestRates.kt | 2 +- .../main/kotlin/net/corda/irs/contract/IRS.kt | 3 ++ .../net/corda/irs/flows/AutoOfferFlow.kt | 2 +- .../kotlin/net/corda/irs/flows/FixingFlow.kt | 2 +- .../net/corda/irs/flows/RatesFixFlow.kt | 2 +- .../corda/irs/flows/UpdateBusinessDayFlow.kt | 2 +- .../kotlin/net/corda/irs/plugin/IRSPlugin.kt | 2 +- .../net/corda/simulation/IRSSimulation.kt | 4 +- .../kotlin/net/corda/irs/testing/IRSTests.kt | 2 +- .../irs/testing/NodeInterestRatesTest.kt | 2 +- .../notarydemo/flows/DummyIssueAndMove.kt | 2 +- .../notarydemo/plugin/NotaryDemoPlugin.kt | 2 +- .../kotlin/net/corda/vega/api/PortfolioApi.kt | 2 + .../net/corda/vega/api/PortfolioApiUtils.kt | 4 +- .../net/corda/vega/api/SwapDataModel.kt | 2 +- .../kotlin/net/corda/vega/api/SwapDataView.kt | 2 +- .../net/corda/vega/contracts/IRSState.kt | 4 +- .../corda/vega/contracts/PortfolioState.kt | 4 +- .../corda/vega/contracts/RevisionedState.kt | 2 +- .../net/corda/vega/contracts/SwapData.kt | 2 +- .../net/corda/vega/flows/IRSTradeFlow.kt | 2 +- .../kotlin/net/corda/vega/flows/SimmFlow.kt | 4 +- .../net/corda/vega/flows/StateRevisionFlow.kt | 2 +- .../net/corda/vega/portfolio/Portfolio.kt | 2 +- .../net/corda/vega/services/SimmService.kt | 2 +- .../net/corda/traderdemo/flow/BuyerFlow.kt | 2 +- .../net/corda/traderdemo/flow/SellerFlow.kt | 2 +- .../traderdemo/plugin/TraderDemoPlugin.kt | 2 +- .../kotlin/net/corda/testing/CoreTestUtils.kt | 1 + .../main/kotlin/net/corda/testing/TestDSL.kt | 1 + .../testing/TransactionDSLInterpreter.kt | 2 +- .../corda/testing/node/MockNetworkMapCache.kt | 4 +- .../kotlin/net/corda/testing/node/MockNode.kt | 4 +- .../net/corda/testing/node/MockServices.kt | 2 + .../explorer/formatters/PartyNameFormatter.kt | 1 - .../corda/explorer/plugin/ExplorerPlugin.kt | 2 +- .../net/corda/explorer/views/GuiUtilities.kt | 4 +- .../net/corda/explorer/views/Network.kt | 2 +- .../corda/explorer/views/TransactionViewer.kt | 2 + .../views/cordapps/cash/CashViewer.kt | 2 +- .../views/cordapps/cash/NewTransaction.kt | 4 +- .../net/corda/loadtest/tests/CrossCashTest.kt | 2 +- .../corda/loadtest/tests/GenerateHelpers.kt | 2 +- .../net/corda/loadtest/tests/SelfIssueTest.kt | 2 +- .../net/corda/verifier/GeneratedLedger.kt | 1 + 178 files changed, 260 insertions(+), 194 deletions(-) rename core/src/main/kotlin/net/corda/core/{crypto => identity}/AbstractParty.kt (96%) rename core/src/main/kotlin/net/corda/core/{crypto => identity}/AnonymousParty.kt (91%) create mode 100644 core/src/main/kotlin/net/corda/core/identity/Party.kt rename core/src/test/kotlin/net/corda/core/{crypto => identity}/PartyTest.kt (90%) diff --git a/client/jackson/src/main/kotlin/net/corda/jackson/JacksonSupport.kt b/client/jackson/src/main/kotlin/net/corda/jackson/JacksonSupport.kt index 1688010b11..361313dbe3 100644 --- a/client/jackson/src/main/kotlin/net/corda/jackson/JacksonSupport.kt +++ b/client/jackson/src/main/kotlin/net/corda/jackson/JacksonSupport.kt @@ -10,6 +10,8 @@ import com.fasterxml.jackson.module.kotlin.KotlinModule import net.corda.core.contracts.Amount import net.corda.core.contracts.BusinessCalendar import net.corda.core.crypto.* +import net.corda.core.identity.AnonymousParty +import net.corda.core.identity.Party import net.corda.core.messaging.CordaRPCOps import net.corda.core.node.NodeInfo import net.corda.core.node.services.IdentityService diff --git a/client/mock/src/main/kotlin/net/corda/client/mock/EventGenerator.kt b/client/mock/src/main/kotlin/net/corda/client/mock/EventGenerator.kt index ef2a511be7..f8effdfa8e 100644 --- a/client/mock/src/main/kotlin/net/corda/client/mock/EventGenerator.kt +++ b/client/mock/src/main/kotlin/net/corda/client/mock/EventGenerator.kt @@ -1,7 +1,7 @@ package net.corda.client.mock import net.corda.core.contracts.Amount -import net.corda.core.crypto.Party +import net.corda.core.identity.Party import net.corda.core.serialization.OpaqueBytes import net.corda.flows.CashFlowCommand import java.util.* diff --git a/core/src/main/kotlin/net/corda/core/contracts/ContractsDSL.kt b/core/src/main/kotlin/net/corda/core/contracts/ContractsDSL.kt index f39e355090..5b62e342f9 100644 --- a/core/src/main/kotlin/net/corda/core/contracts/ContractsDSL.kt +++ b/core/src/main/kotlin/net/corda/core/contracts/ContractsDSL.kt @@ -2,7 +2,7 @@ package net.corda.core.contracts -import net.corda.core.crypto.Party +import net.corda.core.identity.Party import java.security.PublicKey import java.math.BigDecimal import java.util.* diff --git a/core/src/main/kotlin/net/corda/core/contracts/DummyContract.kt b/core/src/main/kotlin/net/corda/core/contracts/DummyContract.kt index 9aca84bb5d..f7116222ac 100644 --- a/core/src/main/kotlin/net/corda/core/contracts/DummyContract.kt +++ b/core/src/main/kotlin/net/corda/core/contracts/DummyContract.kt @@ -1,7 +1,7 @@ package net.corda.core.contracts -import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash +import net.corda.core.identity.Party import net.corda.core.transactions.TransactionBuilder import java.security.PublicKey diff --git a/core/src/main/kotlin/net/corda/core/contracts/FungibleAsset.kt b/core/src/main/kotlin/net/corda/core/contracts/FungibleAsset.kt index 1e65bea48c..da4dca8a32 100644 --- a/core/src/main/kotlin/net/corda/core/contracts/FungibleAsset.kt +++ b/core/src/main/kotlin/net/corda/core/contracts/FungibleAsset.kt @@ -1,6 +1,6 @@ package net.corda.core.contracts -import net.corda.core.crypto.Party +import net.corda.core.identity.Party import net.corda.core.flows.FlowException import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.loggerFor diff --git a/core/src/main/kotlin/net/corda/core/contracts/Structures.kt b/core/src/main/kotlin/net/corda/core/contracts/Structures.kt index f2f4d1091a..6ea81ca9a5 100644 --- a/core/src/main/kotlin/net/corda/core/contracts/Structures.kt +++ b/core/src/main/kotlin/net/corda/core/contracts/Structures.kt @@ -1,11 +1,11 @@ package net.corda.core.contracts import net.corda.core.contracts.clauses.Clause -import net.corda.core.crypto.AnonymousParty -import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash import net.corda.core.flows.FlowLogicRef import net.corda.core.flows.FlowLogicRefFactory +import net.corda.core.identity.AnonymousParty +import net.corda.core.identity.Party import net.corda.core.node.services.ServiceType import net.corda.core.serialization.* import net.corda.core.transactions.TransactionBuilder diff --git a/core/src/main/kotlin/net/corda/core/contracts/TransactionTypes.kt b/core/src/main/kotlin/net/corda/core/contracts/TransactionTypes.kt index 7e3f42bdab..bac9fbde9d 100644 --- a/core/src/main/kotlin/net/corda/core/contracts/TransactionTypes.kt +++ b/core/src/main/kotlin/net/corda/core/contracts/TransactionTypes.kt @@ -1,6 +1,6 @@ package net.corda.core.contracts -import net.corda.core.crypto.Party +import net.corda.core.identity.Party import net.corda.core.serialization.CordaSerializable import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.TransactionBuilder diff --git a/core/src/main/kotlin/net/corda/core/contracts/TransactionVerification.kt b/core/src/main/kotlin/net/corda/core/contracts/TransactionVerification.kt index 0a9ecd1edd..8ad833d7af 100644 --- a/core/src/main/kotlin/net/corda/core/contracts/TransactionVerification.kt +++ b/core/src/main/kotlin/net/corda/core/contracts/TransactionVerification.kt @@ -1,6 +1,6 @@ package net.corda.core.contracts -import net.corda.core.crypto.Party +import net.corda.core.identity.Party import net.corda.core.crypto.SecureHash import net.corda.core.flows.FlowException import net.corda.core.serialization.CordaSerializable diff --git a/core/src/main/kotlin/net/corda/core/crypto/CryptoUtils.kt b/core/src/main/kotlin/net/corda/core/crypto/CryptoUtils.kt index f8f3d6a384..69fe06fd43 100644 --- a/core/src/main/kotlin/net/corda/core/crypto/CryptoUtils.kt +++ b/core/src/main/kotlin/net/corda/core/crypto/CryptoUtils.kt @@ -2,6 +2,7 @@ package net.corda.core.crypto +import net.corda.core.identity.Party import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.OpaqueBytes import net.i2p.crypto.eddsa.EdDSAPublicKey diff --git a/core/src/main/kotlin/net/corda/core/crypto/DigitalSignature.kt b/core/src/main/kotlin/net/corda/core/crypto/DigitalSignature.kt index f9967d103f..01c0a0d2be 100644 --- a/core/src/main/kotlin/net/corda/core/crypto/DigitalSignature.kt +++ b/core/src/main/kotlin/net/corda/core/crypto/DigitalSignature.kt @@ -1,5 +1,6 @@ package net.corda.core.crypto +import net.corda.core.identity.Party import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.OpaqueBytes import java.security.InvalidKeyException diff --git a/core/src/main/kotlin/net/corda/core/crypto/Party.kt b/core/src/main/kotlin/net/corda/core/crypto/Party.kt index 97be9e9e24..883dff284c 100644 --- a/core/src/main/kotlin/net/corda/core/crypto/Party.kt +++ b/core/src/main/kotlin/net/corda/core/crypto/Party.kt @@ -1,33 +1,7 @@ package net.corda.core.crypto -import net.corda.core.contracts.PartyAndReference -import net.corda.core.serialization.OpaqueBytes import org.bouncycastle.asn1.x500.X500Name import java.security.PublicKey -/** - * The [Party] class represents an entity on the network, which is typically identified by a legal [name] and public key - * that it can sign transactions under. As parties may use multiple keys for signing and, for example, have offline backup - * keys, the "public key" of a party can be represented by a composite construct – a [CompositeKey], which combines multiple - * cryptographic public key primitives into a tree structure. - * - * For example: Alice has two key pairs (pub1/priv1 and pub2/priv2), and wants to be able to sign transactions with either of them. - * Her advertised [Party] then has a legal X.500 [name] "CN=Alice Corp,O=Alice Corp,L=London,C=UK" and an [owningKey] - * "pub1 or pub2". - * - * [Party] is also used for service identities. E.g. Alice may also be running an interest rate oracle on her Corda node, - * which requires a separate signing key (and an identifying name). Services can also be distributed – run by a coordinated - * cluster of Corda nodes. A [Party] representing a distributed service will use a composite key containing all - * individual cluster nodes' public keys. Each of the nodes in the cluster will advertise the same group [Party]. - * - * Note that equality is based solely on the owning key. - * - * @see CompositeKey - */ -class Party(val name: X500Name, owningKey: PublicKey) : AbstractParty(owningKey) { - override fun toAnonymous(): AnonymousParty = AnonymousParty(owningKey) - override fun toString() = "${owningKey.toBase58String()} ($name)" - override fun nameOrNull(): X500Name? = name - - override fun ref(bytes: OpaqueBytes): PartyAndReference = PartyAndReference(this.toAnonymous(), bytes) -} +@Deprecated("Party has moved to identity package", ReplaceWith("net.corda.core.identity.Party")) +class Party(name: X500Name, owningKey: PublicKey) : net.corda.core.identity.Party(name, owningKey) \ No newline at end of file diff --git a/core/src/main/kotlin/net/corda/core/flows/FlowLogic.kt b/core/src/main/kotlin/net/corda/core/flows/FlowLogic.kt index 2866a98c01..1fe15cd1f7 100644 --- a/core/src/main/kotlin/net/corda/core/flows/FlowLogic.kt +++ b/core/src/main/kotlin/net/corda/core/flows/FlowLogic.kt @@ -1,8 +1,8 @@ package net.corda.core.flows import co.paralleluniverse.fibers.Suspendable -import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash +import net.corda.core.identity.Party import net.corda.core.node.ServiceHub import net.corda.core.transactions.SignedTransaction import net.corda.core.utilities.ProgressTracker diff --git a/core/src/main/kotlin/net/corda/core/flows/FlowStateMachine.kt b/core/src/main/kotlin/net/corda/core/flows/FlowStateMachine.kt index 398c46c7be..b4d2de2817 100644 --- a/core/src/main/kotlin/net/corda/core/flows/FlowStateMachine.kt +++ b/core/src/main/kotlin/net/corda/core/flows/FlowStateMachine.kt @@ -3,8 +3,8 @@ package net.corda.core.flows import co.paralleluniverse.fibers.Suspendable import com.google.common.util.concurrent.ListenableFuture import net.corda.core.contracts.ScheduledStateRef -import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash +import net.corda.core.identity.Party import net.corda.core.node.ServiceHub import net.corda.core.serialization.CordaSerializable import net.corda.core.transactions.SignedTransaction diff --git a/core/src/main/kotlin/net/corda/core/crypto/AbstractParty.kt b/core/src/main/kotlin/net/corda/core/identity/AbstractParty.kt similarity index 96% rename from core/src/main/kotlin/net/corda/core/crypto/AbstractParty.kt rename to core/src/main/kotlin/net/corda/core/identity/AbstractParty.kt index 7a4249af62..9f90a5267a 100644 --- a/core/src/main/kotlin/net/corda/core/crypto/AbstractParty.kt +++ b/core/src/main/kotlin/net/corda/core/identity/AbstractParty.kt @@ -1,4 +1,4 @@ -package net.corda.core.crypto +package net.corda.core.identity import net.corda.core.contracts.PartyAndReference import net.corda.core.serialization.CordaSerializable diff --git a/core/src/main/kotlin/net/corda/core/crypto/AnonymousParty.kt b/core/src/main/kotlin/net/corda/core/identity/AnonymousParty.kt similarity index 91% rename from core/src/main/kotlin/net/corda/core/crypto/AnonymousParty.kt rename to core/src/main/kotlin/net/corda/core/identity/AnonymousParty.kt index 6b01951d2c..81c04846cc 100644 --- a/core/src/main/kotlin/net/corda/core/crypto/AnonymousParty.kt +++ b/core/src/main/kotlin/net/corda/core/identity/AnonymousParty.kt @@ -1,6 +1,7 @@ -package net.corda.core.crypto +package net.corda.core.identity import net.corda.core.contracts.PartyAndReference +import net.corda.core.crypto.toBase58String import net.corda.core.serialization.OpaqueBytes import org.bouncycastle.asn1.x500.X500Name import java.security.PublicKey diff --git a/core/src/main/kotlin/net/corda/core/identity/Party.kt b/core/src/main/kotlin/net/corda/core/identity/Party.kt new file mode 100644 index 0000000000..1016bb4352 --- /dev/null +++ b/core/src/main/kotlin/net/corda/core/identity/Party.kt @@ -0,0 +1,35 @@ +package net.corda.core.identity + +import net.corda.core.contracts.PartyAndReference +import net.corda.core.crypto.toBase58String +import net.corda.core.serialization.OpaqueBytes +import org.bouncycastle.asn1.x500.X500Name +import java.security.PublicKey + +/** + * The [Party] class represents an entity on the network, which is typically identified by a legal [name] and public key + * that it can sign transactions under. As parties may use multiple keys for signing and, for example, have offline backup + * keys, the "public key" of a party can be represented by a composite construct – a [CompositeKey], which combines multiple + * cryptographic public key primitives into a tree structure. + * + * For example: Alice has two key pairs (pub1/priv1 and pub2/priv2), and wants to be able to sign transactions with either of them. + * Her advertised [Party] then has a legal X.500 [name] "CN=Alice Corp,O=Alice Corp,L=London,C=UK" and an [owningKey] + * "pub1 or pub2". + * + * [Party] is also used for service identities. E.g. Alice may also be running an interest rate oracle on her Corda node, + * which requires a separate signing key (and an identifying name). Services can also be distributed – run by a coordinated + * cluster of Corda nodes. A [Party] representing a distributed service will use a composite key containing all + * individual cluster nodes' public keys. Each of the nodes in the cluster will advertise the same group [Party]. + * + * Note that equality is based solely on the owning key. + * + * @see CompositeKey + */ +// TODO: Remove "open" from [Party] once deprecated crypto.Party class is removed +open class Party(val name: X500Name, owningKey: PublicKey) : AbstractParty(owningKey) { + override fun toAnonymous(): AnonymousParty = AnonymousParty(owningKey) + override fun toString() = "${owningKey.toBase58String()} ($name)" + override fun nameOrNull(): X500Name? = name + + override fun ref(bytes: OpaqueBytes): PartyAndReference = PartyAndReference(this.toAnonymous(), bytes) +} diff --git a/core/src/main/kotlin/net/corda/core/messaging/CordaRPCOps.kt b/core/src/main/kotlin/net/corda/core/messaging/CordaRPCOps.kt index caa018cd6e..d5c4a02de3 100644 --- a/core/src/main/kotlin/net/corda/core/messaging/CordaRPCOps.kt +++ b/core/src/main/kotlin/net/corda/core/messaging/CordaRPCOps.kt @@ -6,11 +6,11 @@ import net.corda.core.contracts.Amount import net.corda.core.contracts.ContractState import net.corda.core.contracts.StateAndRef import net.corda.core.contracts.UpgradedContract -import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash import net.corda.core.flows.FlowInitiator import net.corda.core.flows.FlowLogic import net.corda.core.flows.StateMachineRunId +import net.corda.core.identity.Party import net.corda.core.node.NodeInfo import net.corda.core.node.services.NetworkMapCache import net.corda.core.node.services.StateMachineTransactionMapping diff --git a/core/src/main/kotlin/net/corda/core/node/NodeInfo.kt b/core/src/main/kotlin/net/corda/core/node/NodeInfo.kt index 7c54fc8647..e7c542cdca 100644 --- a/core/src/main/kotlin/net/corda/core/node/NodeInfo.kt +++ b/core/src/main/kotlin/net/corda/core/node/NodeInfo.kt @@ -1,6 +1,6 @@ package net.corda.core.node -import net.corda.core.crypto.Party +import net.corda.core.identity.Party import net.corda.core.messaging.SingleMessageRecipient import net.corda.core.node.services.ServiceInfo import net.corda.core.node.services.ServiceType diff --git a/core/src/main/kotlin/net/corda/core/node/PluginServiceHub.kt b/core/src/main/kotlin/net/corda/core/node/PluginServiceHub.kt index 6f40e356fa..b6ead1d051 100644 --- a/core/src/main/kotlin/net/corda/core/node/PluginServiceHub.kt +++ b/core/src/main/kotlin/net/corda/core/node/PluginServiceHub.kt @@ -1,7 +1,7 @@ package net.corda.core.node -import net.corda.core.crypto.Party import net.corda.core.flows.FlowLogic +import net.corda.core.identity.Party /** * A service hub to be used by the [CordaPluginRegistry] diff --git a/core/src/main/kotlin/net/corda/core/node/services/IdentityService.kt b/core/src/main/kotlin/net/corda/core/node/services/IdentityService.kt index 5342b98006..61fb00b6b3 100644 --- a/core/src/main/kotlin/net/corda/core/node/services/IdentityService.kt +++ b/core/src/main/kotlin/net/corda/core/node/services/IdentityService.kt @@ -1,8 +1,8 @@ package net.corda.core.node.services import net.corda.core.contracts.PartyAndReference -import net.corda.core.crypto.AnonymousParty -import net.corda.core.crypto.Party +import net.corda.core.identity.AnonymousParty +import net.corda.core.identity.Party import org.bouncycastle.asn1.x500.X500Name import java.security.PublicKey diff --git a/core/src/main/kotlin/net/corda/core/node/services/NetworkMapCache.kt b/core/src/main/kotlin/net/corda/core/node/services/NetworkMapCache.kt index 7cbcdbc0ec..027383031d 100644 --- a/core/src/main/kotlin/net/corda/core/node/services/NetworkMapCache.kt +++ b/core/src/main/kotlin/net/corda/core/node/services/NetworkMapCache.kt @@ -2,7 +2,7 @@ package net.corda.core.node.services import com.google.common.util.concurrent.ListenableFuture import net.corda.core.contracts.Contract -import net.corda.core.crypto.Party +import net.corda.core.identity.Party import net.corda.core.node.NodeInfo import net.corda.core.randomOrNull import net.corda.core.serialization.CordaSerializable diff --git a/core/src/main/kotlin/net/corda/core/node/services/PartyInfo.kt b/core/src/main/kotlin/net/corda/core/node/services/PartyInfo.kt index fc7cac1f05..e7ec60dd6f 100644 --- a/core/src/main/kotlin/net/corda/core/node/services/PartyInfo.kt +++ b/core/src/main/kotlin/net/corda/core/node/services/PartyInfo.kt @@ -1,6 +1,6 @@ package net.corda.core.node.services -import net.corda.core.crypto.Party +import net.corda.core.identity.Party import net.corda.core.node.NodeInfo import net.corda.core.node.ServiceEntry diff --git a/core/src/main/kotlin/net/corda/core/node/services/Services.kt b/core/src/main/kotlin/net/corda/core/node/services/Services.kt index 14c6e98c16..c29f534a2e 100644 --- a/core/src/main/kotlin/net/corda/core/node/services/Services.kt +++ b/core/src/main/kotlin/net/corda/core/node/services/Services.kt @@ -5,6 +5,8 @@ import com.google.common.util.concurrent.ListenableFuture import net.corda.core.contracts.* import net.corda.core.crypto.* import net.corda.core.flows.FlowException +import net.corda.core.identity.AbstractParty +import net.corda.core.identity.Party import net.corda.core.node.services.vault.PageSpecification import net.corda.core.node.services.vault.QueryCriteria import net.corda.core.node.services.vault.Sort diff --git a/core/src/main/kotlin/net/corda/core/node/services/UniquenessProvider.kt b/core/src/main/kotlin/net/corda/core/node/services/UniquenessProvider.kt index f0b512e166..53ca51ef12 100644 --- a/core/src/main/kotlin/net/corda/core/node/services/UniquenessProvider.kt +++ b/core/src/main/kotlin/net/corda/core/node/services/UniquenessProvider.kt @@ -1,8 +1,8 @@ package net.corda.core.node.services import net.corda.core.contracts.StateRef -import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash +import net.corda.core.identity.Party import net.corda.core.serialization.CordaSerializable /** diff --git a/core/src/main/kotlin/net/corda/core/serialization/Kryo.kt b/core/src/main/kotlin/net/corda/core/serialization/Kryo.kt index 8a9db4ea35..8eba57307d 100644 --- a/core/src/main/kotlin/net/corda/core/serialization/Kryo.kt +++ b/core/src/main/kotlin/net/corda/core/serialization/Kryo.kt @@ -9,6 +9,7 @@ import com.esotericsoftware.kryo.util.MapReferenceResolver import com.google.common.annotations.VisibleForTesting import net.corda.core.contracts.* import net.corda.core.crypto.* +import net.corda.core.identity.Party import net.corda.core.node.AttachmentsClassLoader import net.corda.core.transactions.WireTransaction import net.corda.core.utilities.LazyPool diff --git a/core/src/main/kotlin/net/corda/core/transactions/BaseTransaction.kt b/core/src/main/kotlin/net/corda/core/transactions/BaseTransaction.kt index 080c54ec42..61010282e8 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/BaseTransaction.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/BaseTransaction.kt @@ -1,7 +1,7 @@ package net.corda.core.transactions import net.corda.core.contracts.* -import net.corda.core.crypto.Party +import net.corda.core.identity.Party import java.security.PublicKey import java.util.* diff --git a/core/src/main/kotlin/net/corda/core/transactions/LedgerTransaction.kt b/core/src/main/kotlin/net/corda/core/transactions/LedgerTransaction.kt index 60f09ec6f9..4665387c7d 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/LedgerTransaction.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/LedgerTransaction.kt @@ -1,8 +1,8 @@ package net.corda.core.transactions import net.corda.core.contracts.* -import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash +import net.corda.core.identity.Party import net.corda.core.serialization.CordaSerializable import java.security.PublicKey diff --git a/core/src/main/kotlin/net/corda/core/transactions/MerkleTransaction.kt b/core/src/main/kotlin/net/corda/core/transactions/MerkleTransaction.kt index 9513f46f8d..952544be36 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/MerkleTransaction.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/MerkleTransaction.kt @@ -2,6 +2,7 @@ package net.corda.core.transactions import net.corda.core.contracts.* import net.corda.core.crypto.* +import net.corda.core.identity.Party import net.corda.core.serialization.CordaSerializable import net.corda.core.serialization.p2PKryo import net.corda.core.serialization.serialize diff --git a/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt b/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt index dbbd0a4856..19396b1e01 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/TransactionBuilder.kt @@ -4,6 +4,7 @@ import co.paralleluniverse.strands.Strand import net.corda.core.contracts.* import net.corda.core.crypto.* import net.corda.core.flows.FlowStateMachine +import net.corda.core.identity.Party import net.corda.core.serialization.serialize import java.security.KeyPair import java.security.PublicKey diff --git a/core/src/main/kotlin/net/corda/core/transactions/WireTransaction.kt b/core/src/main/kotlin/net/corda/core/transactions/WireTransaction.kt index 83c90b9e97..09e2b9218b 100644 --- a/core/src/main/kotlin/net/corda/core/transactions/WireTransaction.kt +++ b/core/src/main/kotlin/net/corda/core/transactions/WireTransaction.kt @@ -3,8 +3,8 @@ package net.corda.core.transactions import com.esotericsoftware.kryo.pool.KryoPool import net.corda.core.contracts.* import net.corda.core.crypto.MerkleTree -import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash +import net.corda.core.identity.Party import net.corda.core.indexOfOrThrow import net.corda.core.node.ServicesForResolution import net.corda.core.serialization.SerializedBytes diff --git a/core/src/main/kotlin/net/corda/core/utilities/TestConstants.kt b/core/src/main/kotlin/net/corda/core/utilities/TestConstants.kt index 1b2fae92e2..1084808a4a 100644 --- a/core/src/main/kotlin/net/corda/core/utilities/TestConstants.kt +++ b/core/src/main/kotlin/net/corda/core/utilities/TestConstants.kt @@ -3,6 +3,7 @@ package net.corda.core.utilities import net.corda.core.crypto.* +import net.corda.core.identity.Party import org.bouncycastle.asn1.x500.X500Name import java.math.BigInteger import java.security.KeyPair diff --git a/core/src/main/kotlin/net/corda/flows/AbstractStateReplacementFlow.kt b/core/src/main/kotlin/net/corda/flows/AbstractStateReplacementFlow.kt index 601ff3df33..fccf706b97 100644 --- a/core/src/main/kotlin/net/corda/flows/AbstractStateReplacementFlow.kt +++ b/core/src/main/kotlin/net/corda/flows/AbstractStateReplacementFlow.kt @@ -7,6 +7,7 @@ import net.corda.core.contracts.StateRef import net.corda.core.crypto.* import net.corda.core.flows.FlowException import net.corda.core.flows.FlowLogic +import net.corda.core.identity.Party import net.corda.core.serialization.CordaSerializable import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.WireTransaction diff --git a/core/src/main/kotlin/net/corda/flows/BroadcastTransactionFlow.kt b/core/src/main/kotlin/net/corda/flows/BroadcastTransactionFlow.kt index 1bfd7a2b79..140da37489 100644 --- a/core/src/main/kotlin/net/corda/flows/BroadcastTransactionFlow.kt +++ b/core/src/main/kotlin/net/corda/flows/BroadcastTransactionFlow.kt @@ -1,9 +1,9 @@ package net.corda.flows import co.paralleluniverse.fibers.Suspendable -import net.corda.core.crypto.Party import net.corda.core.flows.FlowLogic import net.corda.core.flows.InitiatingFlow +import net.corda.core.identity.Party import net.corda.core.serialization.CordaSerializable import net.corda.core.transactions.SignedTransaction diff --git a/core/src/main/kotlin/net/corda/flows/FetchAttachmentsFlow.kt b/core/src/main/kotlin/net/corda/flows/FetchAttachmentsFlow.kt index 096d5bc726..3ca8c8f695 100644 --- a/core/src/main/kotlin/net/corda/flows/FetchAttachmentsFlow.kt +++ b/core/src/main/kotlin/net/corda/flows/FetchAttachmentsFlow.kt @@ -2,10 +2,10 @@ package net.corda.flows import net.corda.core.contracts.AbstractAttachment import net.corda.core.contracts.Attachment -import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash import net.corda.core.crypto.sha256 import net.corda.core.flows.InitiatingFlow +import net.corda.core.identity.Party import net.corda.core.serialization.SerializationToken import net.corda.core.serialization.SerializeAsToken import net.corda.core.serialization.SerializeAsTokenContext diff --git a/core/src/main/kotlin/net/corda/flows/FetchDataFlow.kt b/core/src/main/kotlin/net/corda/flows/FetchDataFlow.kt index 5655b14beb..efbe720210 100644 --- a/core/src/main/kotlin/net/corda/flows/FetchDataFlow.kt +++ b/core/src/main/kotlin/net/corda/flows/FetchDataFlow.kt @@ -2,10 +2,10 @@ package net.corda.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.NamedByHash -import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash import net.corda.core.flows.FlowException import net.corda.core.flows.FlowLogic +import net.corda.core.identity.Party import net.corda.core.serialization.CordaSerializable import net.corda.core.utilities.UntrustworthyData import net.corda.core.utilities.unwrap diff --git a/core/src/main/kotlin/net/corda/flows/FetchTransactionsFlow.kt b/core/src/main/kotlin/net/corda/flows/FetchTransactionsFlow.kt index 96f04477e3..6e9c1055a8 100644 --- a/core/src/main/kotlin/net/corda/flows/FetchTransactionsFlow.kt +++ b/core/src/main/kotlin/net/corda/flows/FetchTransactionsFlow.kt @@ -1,8 +1,8 @@ package net.corda.flows -import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash import net.corda.core.flows.InitiatingFlow +import net.corda.core.identity.Party import net.corda.core.transactions.SignedTransaction /** diff --git a/core/src/main/kotlin/net/corda/flows/FinalityFlow.kt b/core/src/main/kotlin/net/corda/flows/FinalityFlow.kt index 319274f10a..0d1168f42f 100644 --- a/core/src/main/kotlin/net/corda/flows/FinalityFlow.kt +++ b/core/src/main/kotlin/net/corda/flows/FinalityFlow.kt @@ -4,9 +4,9 @@ import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.ContractState import net.corda.core.contracts.StateRef import net.corda.core.contracts.TransactionState -import net.corda.core.crypto.Party import net.corda.core.crypto.isFulfilledBy import net.corda.core.flows.FlowLogic +import net.corda.core.identity.Party import net.corda.core.node.ServiceHub import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.SignedTransaction diff --git a/core/src/main/kotlin/net/corda/flows/NotaryChangeFlow.kt b/core/src/main/kotlin/net/corda/flows/NotaryChangeFlow.kt index ce2985d128..4a80599021 100644 --- a/core/src/main/kotlin/net/corda/flows/NotaryChangeFlow.kt +++ b/core/src/main/kotlin/net/corda/flows/NotaryChangeFlow.kt @@ -1,8 +1,8 @@ package net.corda.flows import net.corda.core.contracts.* -import net.corda.core.crypto.Party import net.corda.core.flows.InitiatingFlow +import net.corda.core.identity.Party import net.corda.core.transactions.SignedTransaction import net.corda.core.transactions.TransactionBuilder import net.corda.core.utilities.ProgressTracker diff --git a/core/src/main/kotlin/net/corda/flows/NotaryFlow.kt b/core/src/main/kotlin/net/corda/flows/NotaryFlow.kt index ca2c4e4024..58819c9c7b 100644 --- a/core/src/main/kotlin/net/corda/flows/NotaryFlow.kt +++ b/core/src/main/kotlin/net/corda/flows/NotaryFlow.kt @@ -7,6 +7,7 @@ import net.corda.core.crypto.* import net.corda.core.flows.FlowException import net.corda.core.flows.FlowLogic import net.corda.core.flows.InitiatingFlow +import net.corda.core.identity.Party import net.corda.core.node.services.TimestampChecker import net.corda.core.node.services.UniquenessException import net.corda.core.node.services.UniquenessProvider diff --git a/core/src/main/kotlin/net/corda/flows/ResolveTransactionsFlow.kt b/core/src/main/kotlin/net/corda/flows/ResolveTransactionsFlow.kt index 69245c7186..1b6d3d4b91 100644 --- a/core/src/main/kotlin/net/corda/flows/ResolveTransactionsFlow.kt +++ b/core/src/main/kotlin/net/corda/flows/ResolveTransactionsFlow.kt @@ -2,10 +2,10 @@ package net.corda.flows import co.paralleluniverse.fibers.Suspendable import net.corda.core.checkedAdd -import net.corda.core.crypto.Party import net.corda.core.crypto.SecureHash import net.corda.core.flows.FlowLogic import net.corda.core.getOrThrow +import net.corda.core.identity.Party import net.corda.core.serialization.CordaSerializable import net.corda.core.transactions.LedgerTransaction import net.corda.core.transactions.SignedTransaction diff --git a/core/src/main/kotlin/net/corda/flows/TwoPartyDealFlow.kt b/core/src/main/kotlin/net/corda/flows/TwoPartyDealFlow.kt index a0e86838c2..6284955239 100644 --- a/core/src/main/kotlin/net/corda/flows/TwoPartyDealFlow.kt +++ b/core/src/main/kotlin/net/corda/flows/TwoPartyDealFlow.kt @@ -4,6 +4,8 @@ import co.paralleluniverse.fibers.Suspendable import net.corda.core.contracts.DealState import net.corda.core.crypto.* import net.corda.core.flows.FlowLogic +import net.corda.core.identity.AbstractParty +import net.corda.core.identity.Party import net.corda.core.node.NodeInfo import net.corda.core.seconds import net.corda.core.serialization.CordaSerializable diff --git a/core/src/main/kotlin/net/corda/flows/TxKeyFlowUtilities.kt b/core/src/main/kotlin/net/corda/flows/TxKeyFlowUtilities.kt index 33db142cc2..4fa07b2e44 100644 --- a/core/src/main/kotlin/net/corda/flows/TxKeyFlowUtilities.kt +++ b/core/src/main/kotlin/net/corda/flows/TxKeyFlowUtilities.kt @@ -1,8 +1,8 @@ package net.corda.flows import co.paralleluniverse.fibers.Suspendable -import net.corda.core.crypto.Party import net.corda.core.flows.FlowLogic +import net.corda.core.identity.Party import net.corda.core.serialization.CordaSerializable import net.corda.core.utilities.unwrap import java.security.PublicKey diff --git a/core/src/main/resources/net/corda/core/node/isolated.jar b/core/src/main/resources/net/corda/core/node/isolated.jar index 450d5f0cdc410c7d295745c7f10af70294592e90..1d6808b4b02b7ee4c71422cdf200148f9dcb27d7 100644 GIT binary patch delta 5749 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