Removes use of notaries.first. (#6008)

This commit is contained in:
Joel Dudley 2020-02-27 13:27:38 +00:00 committed by GitHub
parent 92a437f333
commit 1bf311ce4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 56 additions and 38 deletions

View File

@ -215,7 +215,7 @@ Remember that a transaction generally needs a notary to:
* Prevent double-spends if the transaction has inputs
* Serve as a timestamping authority if the transaction has a time-window
There are several ways to retrieve a notary from the network map:
A notary can be retrieved from the network map as follows:
.. container:: codeset

View File

@ -117,19 +117,14 @@ public class FlowCookbook {
progressTracker.setCurrentStep(ID_OTHER_NODES);
// DOCEND 18
// A transaction generally needs a notary:
// Every transaction needs a notary:
// - To prevent double-spends if the transaction has inputs
// - To serve as a timestamping authority if the transaction has a
// time-window
// We retrieve a notary from the network map.
// DOCSTART 01
CordaX500Name notaryName = new CordaX500Name("Notary Service", "London", "GB");
Party specificNotary = getServiceHub().getNetworkMapCache().getNotary(notaryName);
// Alternatively, we can pick an arbitrary notary from the notary
// list. However, it is always preferable to specify the notary
// explicitly, as the notary list might change when new notaries are
// introduced, or old ones decommissioned.
Party firstNotary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
Party notary = getServiceHub().getNetworkMapCache().getNotary(notaryName);
// DOCEND 01
// We may also need to identify a specific counterparty. We do so
@ -328,7 +323,7 @@ public class FlowCookbook {
// If our transaction has input states or a time-window, we must instantiate it with a
// notary.
// DOCSTART 19
TransactionBuilder txBuilder = new TransactionBuilder(specificNotary);
TransactionBuilder txBuilder = new TransactionBuilder(notary);
// DOCEND 19
// Otherwise, we can choose to instantiate it without one:
@ -362,7 +357,7 @@ public class FlowCookbook {
// An output state can be added as a ``ContractState``, contract class name and notary.
// DOCSTART 49
txBuilder.addOutputState(ourOutputState, DummyContract.PROGRAM_ID, specificNotary);
txBuilder.addOutputState(ourOutputState, DummyContract.PROGRAM_ID, notary);
// DOCEND 49
// We can also leave the notary field blank, in which case the transaction's default
// notary is used.
@ -372,7 +367,7 @@ public class FlowCookbook {
// Or we can add the output state as a ``TransactionState``, which already specifies
// the output's contract and notary.
// DOCSTART 51
TransactionState txState = new TransactionState(ourOutputState, DummyContract.PROGRAM_ID, specificNotary);
TransactionState txState = new TransactionState(ourOutputState, DummyContract.PROGRAM_ID, notary);
// DOCEND 51
// Commands can be added as ``Command``s.

View File

@ -97,7 +97,7 @@ class InitiatorFlow(val arg1: Boolean, val arg2: Int, private val counterparty:
progressTracker.currentStep = ID_OTHER_NODES
// DOCEND 18
// A transaction generally needs a notary:
// Every transaction needs a notary:
// - To prevent double-spends if the transaction has inputs
// - To serve as a timestamping authority if the transaction has a
// time-window
@ -107,12 +107,7 @@ class InitiatorFlow(val arg1: Boolean, val arg2: Int, private val counterparty:
organisation = "Notary Service",
locality = "London",
country = "GB")
val specificNotary: Party = serviceHub.networkMapCache.getNotary(notaryName)!!
// Alternatively, we can pick an arbitrary notary from the notary
// list. However, it is always preferable to specify the notary
// explicitly, as the notary list might change when new notaries are
// introduced, or old ones decommissioned.
val firstNotary: Party = serviceHub.networkMapCache.notaryIdentities.first()
val notary: Party = serviceHub.networkMapCache.getNotary(notaryName)!!
// DOCEND 01
// We may also need to identify a specific counterparty. We do so
@ -328,7 +323,7 @@ class InitiatorFlow(val arg1: Boolean, val arg2: Int, private val counterparty:
// If our transaction has input states or a time-window, we must instantiate it with a
// notary.
// DOCSTART 19
val txBuilder: TransactionBuilder = TransactionBuilder(specificNotary)
val txBuilder: TransactionBuilder = TransactionBuilder(notary)
// DOCEND 19
// Otherwise, we can choose to instantiate it without one:
@ -362,7 +357,7 @@ class InitiatorFlow(val arg1: Boolean, val arg2: Int, private val counterparty:
// An output state can be added as a ``ContractState``, contract class name and notary.
// DOCSTART 49
txBuilder.addOutputState(ourOutputState, DummyContract.PROGRAM_ID, specificNotary)
txBuilder.addOutputState(ourOutputState, DummyContract.PROGRAM_ID, notary)
// DOCEND 49
// We can also leave the notary field blank, in which case the transaction's default
// notary is used.
@ -372,7 +367,7 @@ class InitiatorFlow(val arg1: Boolean, val arg2: Int, private val counterparty:
// Or we can add the output state as a ``TransactionState``, which already specifies
// the output's contract and notary.
// DOCSTART 51
val txState: TransactionState<DummyState> = TransactionState(ourOutputState, DummyContract.PROGRAM_ID, specificNotary)
val txState: TransactionState<DummyState> = TransactionState(ourOutputState, DummyContract.PROGRAM_ID, notary)
// DOCEND 51
// Commands can be added as ``Command``s.

View File

@ -1,10 +1,23 @@
package net.corda.docs.kotlin
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.contracts.*
import net.corda.core.contracts.Amount
import net.corda.core.contracts.Issued
import net.corda.core.contracts.StateAndContract
import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.withoutIssuer
import net.corda.core.crypto.SecureHash
import net.corda.core.crypto.TransactionSignature
import net.corda.core.flows.*
import net.corda.core.flows.FinalityFlow
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.FlowSession
import net.corda.core.flows.InitiatedBy
import net.corda.core.flows.InitiatingFlow
import net.corda.core.flows.ReceiveFinalityFlow
import net.corda.core.flows.ReceiveStateAndRefFlow
import net.corda.core.flows.ReceiveTransactionFlow
import net.corda.core.flows.SendStateAndRefFlow
import net.corda.core.flows.SendTransactionFlow
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party
import net.corda.core.node.ServiceHub
@ -24,7 +37,7 @@ private data class FxRequest(val tradeId: String,
val amount: Amount<Issued<Currency>>,
val owner: Party,
val counterparty: Party,
val notary: Party? = null)
val notary: Party)
// DOCSTART 1
// This is equivalent to the Cash.generateSpend
@ -38,8 +51,7 @@ private fun gatherOurInputs(serviceHub: ServiceHub,
val ourParties = ourKeys.map { serviceHub.identityService.partyFromKey(it) ?: throw IllegalStateException("Unable to resolve party from key") }
val fungibleCriteria = QueryCriteria.FungibleAssetQueryCriteria(owner = ourParties)
val notaries = notary ?: serviceHub.networkMapCache.notaryIdentities.first()
val vaultCriteria: QueryCriteria = QueryCriteria.VaultQueryCriteria(notary = listOf(notaries as AbstractParty))
val vaultCriteria: QueryCriteria = QueryCriteria.VaultQueryCriteria(notary = listOf(notary as AbstractParty))
val logicalExpression = builder { CashSchemaV1.PersistentCashState::currency.equal(amountRequired.token.product.currencyCode) }
val cashCriteria = QueryCriteria.VaultCustomQueryCriteria(logicalExpression)
@ -90,19 +102,20 @@ class ForeignExchangeFlow(private val tradeId: String,
private val baseCurrencyAmount: Amount<Issued<Currency>>,
private val quoteCurrencyAmount: Amount<Issued<Currency>>,
private val counterparty: Party,
private val weAreBaseCurrencySeller: Boolean) : FlowLogic<SecureHash>() {
private val weAreBaseCurrencySeller: Boolean,
private val notary: Party) : FlowLogic<SecureHash>() {
@Suspendable
override fun call(): SecureHash {
// Select correct sides of the Fx exchange to query for.
// Specifically we own the assets we wish to sell.
// Also prepare the other side query
val (localRequest, remoteRequest) = if (weAreBaseCurrencySeller) {
val local = FxRequest(tradeId, baseCurrencyAmount, ourIdentity, counterparty)
val remote = FxRequest(tradeId, quoteCurrencyAmount, counterparty, ourIdentity)
val local = FxRequest(tradeId, baseCurrencyAmount, ourIdentity, counterparty, notary)
val remote = FxRequest(tradeId, quoteCurrencyAmount, counterparty, ourIdentity, notary)
Pair(local, remote)
} else {
val local = FxRequest(tradeId, quoteCurrencyAmount, ourIdentity, counterparty)
val remote = FxRequest(tradeId, baseCurrencyAmount, counterparty, ourIdentity)
val local = FxRequest(tradeId, quoteCurrencyAmount, ourIdentity, counterparty, notary)
val remote = FxRequest(tradeId, baseCurrencyAmount, counterparty, ourIdentity, notary)
Pair(local, remote)
}

View File

@ -3,9 +3,24 @@
package net.corda.docs.kotlin.txbuild
import co.paralleluniverse.fibers.Suspendable
import net.corda.core.contracts.*
import net.corda.core.contracts.Command
import net.corda.core.contracts.CommandData
import net.corda.core.contracts.Contract
import net.corda.core.contracts.LinearState
import net.corda.core.contracts.StateAndContract
import net.corda.core.contracts.StateAndRef
import net.corda.core.contracts.StateRef
import net.corda.core.contracts.TypeOnlyCommandData
import net.corda.core.contracts.UniqueIdentifier
import net.corda.core.contracts.requireSingleCommand
import net.corda.core.contracts.requireThat
import net.corda.core.crypto.TransactionSignature
import net.corda.core.flows.*
import net.corda.core.flows.FinalityFlow
import net.corda.core.flows.FlowLogic
import net.corda.core.flows.FlowSession
import net.corda.core.flows.InitiatedBy
import net.corda.core.flows.InitiatingFlow
import net.corda.core.flows.ReceiveFinalityFlow
import net.corda.core.identity.AbstractParty
import net.corda.core.identity.Party
import net.corda.core.node.services.queryBy
@ -95,13 +110,12 @@ data class TradeApprovalContract(val blank: Unit? = null) : Contract {
*/
@InitiatingFlow
class SubmitTradeApprovalFlow(private val tradeId: String,
private val counterparty: Party) : FlowLogic<StateAndRef<TradeApprovalContract.State>>() {
private val counterparty: Party,
private val notary: Party) : FlowLogic<StateAndRef<TradeApprovalContract.State>>() {
@Suspendable
override fun call(): StateAndRef<TradeApprovalContract.State> {
// Manufacture an initial state
val tradeProposal = TradeApprovalContract.State(tradeId, ourIdentity, counterparty)
// identify a notary. This might also be done external to the flow
val notary = serviceHub.networkMapCache.notaryIdentities.first()
// Create the TransactionBuilder and populate with the new state.
val tx = TransactionBuilder(notary).withItems(
StateAndContract(tradeProposal, TRADE_APPROVAL_PROGRAM_ID),

View File

@ -58,7 +58,8 @@ class FxTransactionBuildTutorialTest {
POUNDS(100).issuedBy(nodeB.info.singleIdentity().ref(0x01)),
DOLLARS(200).issuedBy(nodeA.info.singleIdentity().ref(0x01)),
nodeB.info.singleIdentity(),
weAreBaseCurrencySeller = false)).getOrThrow()
weAreBaseCurrencySeller = false,
notary = mockNet.defaultNotaryIdentity)).getOrThrow()
// wait for the flow to finish and the vault updates to be done
// Get the balances when the vault updates
nodeAVaultUpdate.get()

View File

@ -51,7 +51,7 @@ class WorkflowTransactionBuildTutorialTest {
// Setup a vault subscriber to wait for successful upload of the proposal to NodeB
val nodeBVaultUpdate = bobNode.services.vaultService.updates.toFuture()
// Kick of the proposal flow
val flow1 = aliceNode.startFlow(SubmitTradeApprovalFlow("1234", bob))
val flow1 = aliceNode.startFlow(SubmitTradeApprovalFlow("1234", bob, mockNet.defaultNotaryIdentity))
// Wait for the flow to finish
val proposalRef = flow1.getOrThrow()
val proposalLinearId = proposalRef.state.data.linearId