mirror of
https://github.com/corda/corda.git
synced 2024-12-27 08:22:35 +00:00
Merge remote-tracking branch 'remotes/open/master' into merges/march-6-16-56
# Conflicts: # node/src/main/kotlin/net/corda/node/services/config/NodeConfiguration.kt
This commit is contained in:
commit
906dae11ad
@ -19,3 +19,6 @@ dependencies {
|
|||||||
project(it.path)
|
project(it.path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Don't create an empty jar. The plugins are now in child projects.
|
||||||
|
jar.enabled = false
|
||||||
|
@ -12,7 +12,7 @@ import net.corda.core.utilities.unwrap
|
|||||||
|
|
||||||
object IdentitySyncFlow {
|
object IdentitySyncFlow {
|
||||||
/**
|
/**
|
||||||
* Flow for ensuring that our counter-parties in a transaction have the full certificate paths for *our*
|
* Flow for ensuring that our counterparties in a transaction have the full certificate paths for *our*
|
||||||
* confidential identities used in states present in the transaction. This is intended for use as a sub-flow of
|
* confidential identities used in states present in the transaction. This is intended for use as a sub-flow of
|
||||||
* another flow, typically between transaction assembly and signing. An example of where this is useful is where
|
* another flow, typically between transaction assembly and signing. An example of where this is useful is where
|
||||||
* a recipient of a state wants to know that it is being paid by the correct party, and the owner of the state is a
|
* a recipient of a state wants to know that it is being paid by the correct party, and the owner of the state is a
|
||||||
|
@ -64,7 +64,7 @@ class SwapIdentitiesFlow(private val otherParty: Party,
|
|||||||
throw SwapIdentitiesException("Signature does not match the expected identity ownership assertion.", ex)
|
throw SwapIdentitiesException("Signature does not match the expected identity ownership assertion.", ex)
|
||||||
}
|
}
|
||||||
// Validate then store their identity so that we can prove the key in the transaction is owned by the
|
// Validate then store their identity so that we can prove the key in the transaction is owned by the
|
||||||
// counter-party.
|
// counterparty.
|
||||||
identityService.verifyAndRegisterIdentity(anonymousOtherSide)
|
identityService.verifyAndRegisterIdentity(anonymousOtherSide)
|
||||||
return anonymousOtherSide
|
return anonymousOtherSide
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ import net.corda.core.utilities.unwrap
|
|||||||
import java.security.PublicKey
|
import java.security.PublicKey
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The [CollectSignaturesFlow] is used to automate the collection of counter-party signatures for a given transaction.
|
* The [CollectSignaturesFlow] is used to automate the collection of counterparty signatures for a given transaction.
|
||||||
*
|
*
|
||||||
* You would typically use this flow after you have built a transaction with the TransactionBuilder and signed it with
|
* You would typically use this flow after you have built a transaction with the TransactionBuilder and signed it with
|
||||||
* your key pair. If there are additional signatures to collect then they can be collected using this flow. Signatures
|
* your key pair. If there are additional signatures to collect then they can be collected using this flow. Signatures
|
||||||
@ -35,9 +35,9 @@ import java.security.PublicKey
|
|||||||
* 2. Any of the required signing parties cannot be found in the [ServiceHub.networkMapCache] of the initiator
|
* 2. Any of the required signing parties cannot be found in the [ServiceHub.networkMapCache] of the initiator
|
||||||
* 3. If the wrong key has been used by a counterparty to sign the transaction
|
* 3. If the wrong key has been used by a counterparty to sign the transaction
|
||||||
* 4. The counterparty rejects the provided transaction
|
* 4. The counterparty rejects the provided transaction
|
||||||
* - The flow will return a [SignedTransaction] with all the counter-party signatures (but not the notary's!)
|
* - The flow will return a [SignedTransaction] with all the counterparty signatures (but not the notary's!)
|
||||||
* - If the provided transaction has already been signed by all counter-parties then this flow simply returns the
|
* - If the provided transaction has already been signed by all counterparties then this flow simply returns the
|
||||||
* provided transaction without contacting any counter-parties
|
* provided transaction without contacting any counterparties
|
||||||
* - Call the [FinalityFlow] with the return value of this flow
|
* - Call the [FinalityFlow] with the return value of this flow
|
||||||
*
|
*
|
||||||
* Example - issuing a multi-lateral agreement which requires N signatures:
|
* Example - issuing a multi-lateral agreement which requires N signatures:
|
||||||
@ -68,13 +68,13 @@ class CollectSignaturesFlow @JvmOverloads constructor(val partiallySignedTx: Sig
|
|||||||
@JvmOverloads constructor(partiallySignedTx: SignedTransaction, sessionsToCollectFrom: Collection<FlowSession>, progressTracker: ProgressTracker = CollectSignaturesFlow.tracker()) : this(partiallySignedTx, sessionsToCollectFrom, null, progressTracker)
|
@JvmOverloads constructor(partiallySignedTx: SignedTransaction, sessionsToCollectFrom: Collection<FlowSession>, progressTracker: ProgressTracker = CollectSignaturesFlow.tracker()) : this(partiallySignedTx, sessionsToCollectFrom, null, progressTracker)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
object COLLECTING : ProgressTracker.Step("Collecting signatures from counter-parties.")
|
object COLLECTING : ProgressTracker.Step("Collecting signatures from counterparties.")
|
||||||
object VERIFYING : ProgressTracker.Step("Verifying collected signatures.")
|
object VERIFYING : ProgressTracker.Step("Verifying collected signatures.")
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun tracker() = ProgressTracker(COLLECTING, VERIFYING)
|
fun tracker() = ProgressTracker(COLLECTING, VERIFYING)
|
||||||
|
|
||||||
// TODO: Make the progress tracker adapt to the number of counter-parties to collect from.
|
// TODO: Make the progress tracker adapt to the number of counterparties to collect from.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,7 +101,7 @@ class CollectSignaturesFlow @JvmOverloads constructor(val partiallySignedTx: Sig
|
|||||||
// the FinalityFlow.
|
// the FinalityFlow.
|
||||||
val unsigned = if (notaryKey != null) notSigned - notaryKey else notSigned
|
val unsigned = if (notaryKey != null) notSigned - notaryKey else notSigned
|
||||||
|
|
||||||
// If the unsigned counter-parties list is empty then we don't need to collect any more signatures here.
|
// If the unsigned counterparties list is empty then we don't need to collect any more signatures here.
|
||||||
if (unsigned.isEmpty()) return partiallySignedTx
|
if (unsigned.isEmpty()) return partiallySignedTx
|
||||||
|
|
||||||
val partyToKeysMap = groupPublicKeysByWellKnownParty(serviceHub, unsigned)
|
val partyToKeysMap = groupPublicKeysByWellKnownParty(serviceHub, unsigned)
|
||||||
@ -109,7 +109,7 @@ class CollectSignaturesFlow @JvmOverloads constructor(val partiallySignedTx: Sig
|
|||||||
require(sessionsToCollectFrom.map { it.counterparty }.toSet() == partyToKeysMap.keys) {
|
require(sessionsToCollectFrom.map { it.counterparty }.toSet() == partyToKeysMap.keys) {
|
||||||
"The Initiator of CollectSignaturesFlow must pass in exactly the sessions required to sign the transaction."
|
"The Initiator of CollectSignaturesFlow must pass in exactly the sessions required to sign the transaction."
|
||||||
}
|
}
|
||||||
// Collect signatures from all counter-parties and append them to the partially signed transaction.
|
// Collect signatures from all counterparties and append them to the partially signed transaction.
|
||||||
val counterpartySignatures = sessionsToCollectFrom.flatMap { session ->
|
val counterpartySignatures = sessionsToCollectFrom.flatMap { session ->
|
||||||
subFlow(CollectSignatureFlow(partiallySignedTx, session, partyToKeysMap[session.counterparty]!!))
|
subFlow(CollectSignatureFlow(partiallySignedTx, session, partyToKeysMap[session.counterparty]!!))
|
||||||
}
|
}
|
||||||
@ -161,7 +161,7 @@ class CollectSignatureFlow(val partiallySignedTx: SignedTransaction, val session
|
|||||||
*
|
*
|
||||||
* 1. Should actually be signed by the [Party] invoking this flow
|
* 1. Should actually be signed by the [Party] invoking this flow
|
||||||
* 2. Is valid as per the contracts referenced in the transaction
|
* 2. Is valid as per the contracts referenced in the transaction
|
||||||
* 3. Has been, at least, signed by the counter-party which created it
|
* 3. Has been, at least, signed by the counterparty which created it
|
||||||
* 4. Conforms to custom checking provided in the [checkTransaction] method of the [SignTransactionFlow]
|
* 4. Conforms to custom checking provided in the [checkTransaction] method of the [SignTransactionFlow]
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
@ -258,7 +258,7 @@ abstract class SignTransactionFlow(val otherSideSession: FlowSession,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The [checkTransaction] method allows the caller of this flow to provide some additional checks over the proposed
|
* The [checkTransaction] method allows the caller of this flow to provide some additional checks over the proposed
|
||||||
* transaction received from the counter-party. For example:
|
* transaction received from the counterparty. For example:
|
||||||
*
|
*
|
||||||
* - Ensuring that the transaction you are receiving is the transaction you *EXPECT* to receive. I.e. is has the
|
* - Ensuring that the transaction you are receiving is the transaction you *EXPECT* to receive. I.e. is has the
|
||||||
* expected type and number of inputs and outputs
|
* expected type and number of inputs and outputs
|
||||||
@ -273,7 +273,7 @@ abstract class SignTransactionFlow(val otherSideSession: FlowSession,
|
|||||||
* [IllegalArgumentException], [IllegalStateException] and [AssertionError] will be caught and rethrown as flow
|
* [IllegalArgumentException], [IllegalStateException] and [AssertionError] will be caught and rethrown as flow
|
||||||
* exceptions i.e. the other side will be given information about what exact check failed.
|
* exceptions i.e. the other side will be given information about what exact check failed.
|
||||||
*
|
*
|
||||||
* @param stx a partially signed transaction received from your counter-party.
|
* @param stx a partially signed transaction received from your counterparty.
|
||||||
* @throws FlowException if the proposed transaction fails the checks.
|
* @throws FlowException if the proposed transaction fails the checks.
|
||||||
*/
|
*/
|
||||||
@Suspendable
|
@Suspendable
|
||||||
|
@ -360,7 +360,7 @@ interface CordaRPCOps : RPCOps {
|
|||||||
|
|
||||||
/** Sets the value of the node's flows draining mode.
|
/** Sets the value of the node's flows draining mode.
|
||||||
* If this mode is [enabled], the node will reject new flows through RPC, ignore scheduled flows, and do not process
|
* If this mode is [enabled], the node will reject new flows through RPC, ignore scheduled flows, and do not process
|
||||||
* initial session messages, meaning that P2P counter-parties will not be able to initiate new flows involving the node.
|
* initial session messages, meaning that P2P counterparties will not be able to initiate new flows involving the node.
|
||||||
*
|
*
|
||||||
* @param enabled whether the flows draining mode will be enabled.
|
* @param enabled whether the flows draining mode will be enabled.
|
||||||
* */
|
* */
|
||||||
|
@ -421,7 +421,7 @@ Subflows
|
|||||||
Subflows are pieces of reusable flows that may be run by calling ``FlowLogic.subFlow``. There are two broad categories
|
Subflows are pieces of reusable flows that may be run by calling ``FlowLogic.subFlow``. There are two broad categories
|
||||||
of subflows, inlined and initiating ones. The main difference lies in the counter-flow's starting method, initiating
|
of subflows, inlined and initiating ones. The main difference lies in the counter-flow's starting method, initiating
|
||||||
ones initiate counter-flows automatically, while inlined ones expect some parent counter-flow to run the inlined
|
ones initiate counter-flows automatically, while inlined ones expect some parent counter-flow to run the inlined
|
||||||
counter-part.
|
counterpart.
|
||||||
|
|
||||||
Inlined subflows
|
Inlined subflows
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
|
@ -76,14 +76,14 @@ You can see an example of using ``SwapIdentitiesFlow`` in ``TwoPartyDealFlow.kt`
|
|||||||
|
|
||||||
1. Generate a new confidential identity from our well-known identity
|
1. Generate a new confidential identity from our well-known identity
|
||||||
2. Create a ``CertificateOwnershipAssertion`` object containing the new confidential identity (X500 name, public key)
|
2. Create a ``CertificateOwnershipAssertion`` object containing the new confidential identity (X500 name, public key)
|
||||||
5. Sign this object with the confidential identity's private key
|
3. Sign this object with the confidential identity's private key
|
||||||
6. Send the confidential identity and aforementioned signature to counter-parties, while receiving theirs
|
4. Send the confidential identity and aforementioned signature to counterparties, while receiving theirs
|
||||||
7. Verify the signatures to ensure that identities were generated by the involved set of parties
|
5. Verify the signatures to ensure that identities were generated by the involved set of parties
|
||||||
8. Verify the confidential identities are owned by the expected well known identities
|
6. Verify the confidential identities are owned by the expected well known identities
|
||||||
9. Store the confidential identities and return them to the calling flow
|
7. Store the confidential identities and return them to the calling flow
|
||||||
|
|
||||||
This ensures not only that the confidential identity X.509 certificates are signed by the correct well-known
|
This ensures not only that the confidential identity X.509 certificates are signed by the correct well-known
|
||||||
identities, but also that the confidential identity private key is held by the counter-party, and that a party cannot
|
identities, but also that the confidential identity private key is held by the counterparty, and that a party cannot
|
||||||
claim ownership of another party's confidential identities.
|
claim ownership of another party's confidential identities.
|
||||||
|
|
||||||
IdentitySyncFlow
|
IdentitySyncFlow
|
||||||
|
@ -27,10 +27,10 @@ The flow returns the same transactions, in the same order, with the additional s
|
|||||||
CollectSignaturesFlow
|
CollectSignaturesFlow
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
The ``CollectSignaturesFlow`` is used to automate the collection of signatures from the counter-parties to a transaction.
|
The ``CollectSignaturesFlow`` is used to automate the collection of signatures from the counterparties to a transaction.
|
||||||
|
|
||||||
You use the ``CollectSignaturesFlow`` by passing it a ``SignedTransaction`` which has at least been signed by yourself.
|
You use the ``CollectSignaturesFlow`` by passing it a ``SignedTransaction`` which has at least been signed by yourself.
|
||||||
The flow will handle the resolution of the counter-party identities and request a signature from each counter-party.
|
The flow will handle the resolution of the counterparty identities and request a signature from each counterparty.
|
||||||
|
|
||||||
Finally, the flow will verify all the signatures and return a ``SignedTransaction`` with all the collected signatures.
|
Finally, the flow will verify all the signatures and return a ``SignedTransaction`` with all the collected signatures.
|
||||||
|
|
||||||
|
@ -315,7 +315,7 @@ of the page, and enter the IOU details into the web-form. The IOU must have a po
|
|||||||
|
|
||||||
.. sourcecode:: none
|
.. sourcecode:: none
|
||||||
|
|
||||||
Counter-party: Select from list
|
Counterparty: Select from list
|
||||||
Value (Int): 5
|
Value (Int): 5
|
||||||
|
|
||||||
And click submit. Upon clicking submit, the modal dialogue will close, and the nodes will agree the IOU.
|
And click submit. Upon clicking submit, the modal dialogue will close, and the nodes will agree the IOU.
|
||||||
@ -375,7 +375,7 @@ This will print out the following progress steps:
|
|||||||
✅ Verifying contract constraints.
|
✅ Verifying contract constraints.
|
||||||
✅ Signing transaction with our private key.
|
✅ Signing transaction with our private key.
|
||||||
✅ Gathering the counterparty's signature.
|
✅ Gathering the counterparty's signature.
|
||||||
✅ Collecting signatures from counter-parties.
|
✅ Collecting signatures from counterparties.
|
||||||
✅ Verifying collected signatures.
|
✅ Verifying collected signatures.
|
||||||
✅ Obtaining notary signature and recording transaction.
|
✅ Obtaining notary signature and recording transaction.
|
||||||
✅ Requesting signature by notary service
|
✅ Requesting signature by notary service
|
||||||
|
@ -31,7 +31,7 @@ interface StartedNode<out N : AbstractNode> {
|
|||||||
/**
|
/**
|
||||||
* Use this method to register your initiated flows in your tests. This is automatically done by the node when it
|
* Use this method to register your initiated flows in your tests. This is automatically done by the node when it
|
||||||
* starts up for all [FlowLogic] classes it finds which are annotated with [InitiatedBy].
|
* starts up for all [FlowLogic] classes it finds which are annotated with [InitiatedBy].
|
||||||
* @return An [Observable] of the initiated flows started by counter-parties.
|
* @return An [Observable] of the initiated flows started by counterparties.
|
||||||
*/
|
*/
|
||||||
fun <T : FlowLogic<*>> registerInitiatedFlow(initiatedFlowClass: Class<T>) = internals.registerInitiatedFlow(smm, initiatedFlowClass)
|
fun <T : FlowLogic<*>> registerInitiatedFlow(initiatedFlowClass: Class<T>) = internals.registerInitiatedFlow(smm, initiatedFlowClass)
|
||||||
|
|
||||||
|
@ -177,8 +177,10 @@ data class NodeConfigurationImpl(
|
|||||||
override val attachmentCacheBound: Long = NodeConfiguration.defaultAttachmentCacheBound,
|
override val attachmentCacheBound: Long = NodeConfiguration.defaultAttachmentCacheBound,
|
||||||
override val graphiteOptions: GraphiteOptions? = null,
|
override val graphiteOptions: GraphiteOptions? = null,
|
||||||
// do not use or remove (breaks DemoBench together with rejection of unknown configuration keys during parsing)
|
// do not use or remove (breaks DemoBench together with rejection of unknown configuration keys during parsing)
|
||||||
private val h2port: Int = 0
|
private val h2port: Int = 0,
|
||||||
) : NodeConfiguration {
|
// do not use or remove (used by Capsule)
|
||||||
|
private val jarDirs: List<String> = emptyList()
|
||||||
|
) : NodeConfiguration {
|
||||||
companion object {
|
companion object {
|
||||||
private val logger = loggerFor<NodeConfigurationImpl>()
|
private val logger = loggerFor<NodeConfigurationImpl>()
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ The response should be something like
|
|||||||
}
|
}
|
||||||
|
|
||||||
Now, if we ask the same question of Bank C we will see that it's id matches the id for Bank C as a counter
|
Now, if we ask the same question of Bank C we will see that it's id matches the id for Bank C as a counter
|
||||||
party to Bank A and Bank A will appear as a counter party
|
party to Bank A and Bank A will appear as a counterparty
|
||||||
|
|
||||||
curl -i -H "Content-Type: application/json" -X GET http://localhost:10011/api/simmvaluationdemo/whoami
|
curl -i -H "Content-Type: application/json" -X GET http://localhost:10011/api/simmvaluationdemo/whoami
|
||||||
|
|
||||||
@ -104,9 +104,9 @@ party to Bank A and Bank A will appear as a counter party
|
|||||||
In what follows, we assume we are Bank A (which is listening on port 10005)
|
In what follows, we assume we are Bank A (which is listening on port 10005)
|
||||||
|
|
||||||
Notice the id field in the output of the ``whoami`` command. We are going to use the id associated
|
Notice the id field in the output of the ``whoami`` command. We are going to use the id associated
|
||||||
with Bank C, one of our counter parties, to create a trade. The general command for this is:
|
with Bank C, one of our counterparties, to create a trade. The general command for this is:
|
||||||
|
|
||||||
curl -i -H "Content-Type: application/json" -X PUT -d <<<JSON representation of the trade>>> http://localhost:10005/api/simmvaluationdemo/<<<counter party id>>>/trades
|
curl -i -H "Content-Type: application/json" -X PUT -d <<<JSON representation of the trade>>> http://localhost:10005/api/simmvaluationdemo/<<<counterparty id>>>/trades
|
||||||
|
|
||||||
where the representation of the trade is
|
where the representation of the trade is
|
||||||
|
|
||||||
@ -152,7 +152,7 @@ Once executed, the expected response is:
|
|||||||
|
|
||||||
With the trade completed and stored by both parties, the complete list of trades with our counterparty can be seen with the following command
|
With the trade completed and stored by both parties, the complete list of trades with our counterparty can be seen with the following command
|
||||||
|
|
||||||
curl -X GET http://localhost:10005/api/simmvaluationdemo/<<<counter party id>>>/trades
|
curl -X GET http://localhost:10005/api/simmvaluationdemo/<<<counterparty id>>>/trades
|
||||||
|
|
||||||
The command for our example, using Bank A, would thus be
|
The command for our example, using Bank A, would thus be
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ The command for our example, using Bank A, would thus be
|
|||||||
whilst a specific trade can be seen with
|
whilst a specific trade can be seen with
|
||||||
|
|
||||||
|
|
||||||
curl -X GET http://localhost:10005/api/simmvaluationdemo/<<<counter party id>>>/trades/<<<trade id>>>
|
curl -X GET http://localhost:10005/api/simmvaluationdemo/<<<counterparty id>>>/trades/<<<trade id>>>
|
||||||
|
|
||||||
If we look at the trade we created above, we assigned it the id "trade1", the complete command in this case would be
|
If we look at the trade we created above, we assigned it the id "trade1", the complete command in this case would be
|
||||||
|
|
||||||
@ -172,7 +172,7 @@ If we look at the trade we created above, we assigned it the id "trade1", the co
|
|||||||
curl -i -H "Content-Type: application/json" \
|
curl -i -H "Content-Type: application/json" \
|
||||||
-X POST \
|
-X POST \
|
||||||
-d <<<JSON representation>>>
|
-d <<<JSON representation>>>
|
||||||
http://localhost:10005/api/simmvaluationdemo/<<<counter party id>>>/portfolio/valuations/calculate
|
http://localhost:10005/api/simmvaluationdemo/<<<counterparty id>>>/portfolio/valuations/calculate
|
||||||
|
|
||||||
Again, the specific command to continue our example would be
|
Again, the specific command to continue our example would be
|
||||||
|
|
||||||
@ -183,9 +183,9 @@ Again, the specific command to continue our example would be
|
|||||||
|
|
||||||
**Viewing a valuation**
|
**Viewing a valuation**
|
||||||
|
|
||||||
In the same way we can ask for specific instances of trades with a counter party, we can request details of valuations
|
In the same way we can ask for specific instances of trades with a counterparty, we can request details of valuations
|
||||||
|
|
||||||
curl -i -H "Content-Type: application/json" -X GET http://localhost:10005/api/simmvaluationdemo/<<<counter party id>>>/portfolio/valuations
|
curl -i -H "Content-Type: application/json" -X GET http://localhost:10005/api/simmvaluationdemo/<<<counterparty id>>>/portfolio/valuations
|
||||||
|
|
||||||
The specific command for out Bank A example is
|
The specific command for out Bank A example is
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user