mirror of
https://github.com/corda/corda.git
synced 2025-06-22 17:09:00 +00:00
Updates tutorial to match PR on master. (#4226)
* Updates V3 tutorial to match master tutorial. * Self-review.
This commit is contained in:
@ -1,8 +1,10 @@
|
||||
// We purposefully have this template here as part of progressing through the tutorial
|
||||
package com.template;
|
||||
|
||||
import net.corda.core.contracts.CommandData;
|
||||
import net.corda.core.contracts.Contract;
|
||||
import net.corda.core.transactions.LedgerTransaction;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class TemplateContract implements Contract {
|
||||
// This is used to identify our contract when building a transaction.
|
||||
@ -13,9 +15,9 @@ public class TemplateContract implements Contract {
|
||||
* and output states does not throw an exception.
|
||||
*/
|
||||
@Override
|
||||
public void verify(LedgerTransaction tx) {}
|
||||
public void verify(@NotNull LedgerTransaction tx) {}
|
||||
|
||||
public interface Commands extends CommandData {
|
||||
class Action implements Commands {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,18 +2,21 @@ package net.corda.docs.java.tutorial.helloworld;
|
||||
|
||||
import co.paralleluniverse.fibers.Suspendable;
|
||||
import com.template.TemplateContract;
|
||||
import net.corda.core.flows.*;
|
||||
import net.corda.core.flows.FlowException;
|
||||
import net.corda.core.flows.FlowLogic;
|
||||
import net.corda.core.flows.InitiatingFlow;
|
||||
import net.corda.core.flows.StartableByRPC;
|
||||
import net.corda.core.utilities.ProgressTracker;
|
||||
|
||||
// DOCSTART 01
|
||||
// Add these imports:
|
||||
import net.corda.core.contracts.Command;
|
||||
import net.corda.core.contracts.CommandData;
|
||||
import net.corda.core.flows.FinalityFlow;
|
||||
import net.corda.core.identity.Party;
|
||||
import net.corda.core.transactions.SignedTransaction;
|
||||
import net.corda.core.transactions.TransactionBuilder;
|
||||
import net.corda.core.utilities.ProgressTracker;
|
||||
|
||||
// Replace TemplateFlow's definition with:
|
||||
// Replace Initiator's definition with:
|
||||
@InitiatingFlow
|
||||
@StartableByRPC
|
||||
public class IOUFlow extends FlowLogic<Void> {
|
||||
@ -42,20 +45,19 @@ public class IOUFlow extends FlowLogic<Void> {
|
||||
@Override
|
||||
public Void call() throws FlowException {
|
||||
// We retrieve the notary identity from the network map.
|
||||
final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
|
||||
Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
|
||||
|
||||
// We create the transaction components.
|
||||
IOUState outputState = new IOUState(iouValue, getOurIdentity(), otherParty);
|
||||
CommandData cmdType = new TemplateContract.Commands.Action();
|
||||
Command cmd = new Command<>(cmdType, getOurIdentity().getOwningKey());
|
||||
Command command = new Command<>(new TemplateContract.Commands.Action(), getOurIdentity().getOwningKey());
|
||||
|
||||
// We create a transaction builder and add the components.
|
||||
final TransactionBuilder txBuilder = new TransactionBuilder(notary)
|
||||
TransactionBuilder txBuilder = new TransactionBuilder(notary)
|
||||
.addOutputState(outputState, TemplateContract.ID)
|
||||
.addCommand(cmd);
|
||||
.addCommand(command);
|
||||
|
||||
// Signing the transaction.
|
||||
final SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder);
|
||||
SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder);
|
||||
|
||||
// Finalising the transaction.
|
||||
subFlow(new FinalityFlow(signedTx));
|
||||
@ -63,4 +65,4 @@ public class IOUFlow extends FlowLogic<Void> {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// DOCEND 01
|
||||
// DOCEND 01
|
||||
|
@ -2,11 +2,11 @@ package net.corda.docs.java.tutorial.helloworld;
|
||||
|
||||
import net.corda.core.contracts.ContractState;
|
||||
import net.corda.core.identity.AbstractParty;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
// DOCSTART 01
|
||||
// Add these imports:
|
||||
import com.google.common.collect.ImmutableList;
|
||||
// Add this import:
|
||||
import net.corda.core.identity.Party;
|
||||
|
||||
// Replace TemplateState's definition with:
|
||||
@ -35,7 +35,7 @@ public class IOUState implements ContractState {
|
||||
|
||||
@Override
|
||||
public List<AbstractParty> getParticipants() {
|
||||
return ImmutableList.of(lender, borrower);
|
||||
return Arrays.asList(lender, borrower);
|
||||
}
|
||||
}
|
||||
// DOCEND 01
|
@ -6,15 +6,14 @@ import net.corda.core.transactions.LedgerTransaction;
|
||||
|
||||
// DOCSTART 01
|
||||
// Add these imports:
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.corda.core.contracts.CommandWithParties;
|
||||
import net.corda.core.identity.Party;
|
||||
|
||||
import java.security.PublicKey;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static net.corda.core.contracts.ContractsDSL.requireSingleCommand;
|
||||
import static net.corda.core.contracts.ContractsDSL.requireThat;
|
||||
|
||||
// Replace TemplateContract's definition with:
|
||||
public class IOUContract implements Contract {
|
||||
@ -28,26 +27,29 @@ public class IOUContract implements Contract {
|
||||
public void verify(LedgerTransaction tx) {
|
||||
final CommandWithParties<IOUContract.Create> command = requireSingleCommand(tx.getCommands(), IOUContract.Create.class);
|
||||
|
||||
requireThat(check -> {
|
||||
// Constraints on the shape of the transaction.
|
||||
check.using("No inputs should be consumed when issuing an IOU.", tx.getInputs().isEmpty());
|
||||
check.using("There should be one output state of type IOUState.", tx.getOutputs().size() == 1);
|
||||
// Constraints on the shape of the transaction.
|
||||
if (!tx.getInputs().isEmpty())
|
||||
throw new IllegalArgumentException("No inputs should be consumed when issuing an IOU.");
|
||||
if (!(tx.getOutputs().size() == 1))
|
||||
throw new IllegalArgumentException("There should be one output state of type IOUState.");
|
||||
|
||||
// IOU-specific constraints.
|
||||
final IOUState out = tx.outputsOfType(IOUState.class).get(0);
|
||||
final Party lender = out.getLender();
|
||||
final Party borrower = out.getBorrower();
|
||||
check.using("The IOU's value must be non-negative.", out.getValue() > 0);
|
||||
check.using("The lender and the borrower cannot be the same entity.", lender != borrower);
|
||||
// IOU-specific constraints.
|
||||
final IOUState output = tx.outputsOfType(IOUState.class).get(0);
|
||||
final Party lender = output.getLender();
|
||||
final Party borrower = output.getBorrower();
|
||||
if (output.getValue() <= 0)
|
||||
throw new IllegalArgumentException("The IOU's value must be non-negative.");
|
||||
if (lender.equals(borrower))
|
||||
throw new IllegalArgumentException("The lender and the borrower cannot be the same entity.");
|
||||
|
||||
// Constraints on the signers.
|
||||
final List<PublicKey> signers = command.getSigners();
|
||||
check.using("There must be two signers.", signers.size() == 2);
|
||||
check.using("The borrower and lender must be signers.", signers.containsAll(
|
||||
ImmutableList.of(borrower.getOwningKey(), lender.getOwningKey())));
|
||||
// Constraints on the signers.
|
||||
final List<PublicKey> requiredSigners = command.getSigners();
|
||||
final List<PublicKey> expectedSigners = Arrays.asList(borrower.getOwningKey(), lender.getOwningKey());
|
||||
if (requiredSigners.size() != 2)
|
||||
throw new IllegalArgumentException("There must be two signers.");
|
||||
if (!(requiredSigners.containsAll(expectedSigners)))
|
||||
throw new IllegalArgumentException("The borrower and lender must be signers.");
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
// DOCEND 01
|
@ -2,9 +2,7 @@ package net.corda.docs.java.tutorial.twoparty;
|
||||
|
||||
// DOCSTART 01
|
||||
import co.paralleluniverse.fibers.Suspendable;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.corda.core.contracts.Command;
|
||||
import net.corda.core.contracts.StateAndContract;
|
||||
import net.corda.core.flows.*;
|
||||
import net.corda.core.identity.Party;
|
||||
import net.corda.core.transactions.SignedTransaction;
|
||||
@ -12,6 +10,7 @@ import net.corda.core.transactions.TransactionBuilder;
|
||||
import net.corda.core.utilities.ProgressTracker;
|
||||
|
||||
import java.security.PublicKey;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
// DOCEND 01
|
||||
|
||||
@ -42,35 +41,32 @@ public class IOUFlow extends FlowLogic<Void> {
|
||||
@Suspendable
|
||||
@Override
|
||||
public Void call() throws FlowException {
|
||||
// We retrieve the notary identity from the network map.
|
||||
final Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
|
||||
|
||||
// DOCSTART 02
|
||||
// We create a transaction builder.
|
||||
final TransactionBuilder txBuilder = new TransactionBuilder();
|
||||
txBuilder.setNotary(notary);
|
||||
// We retrieve the notary identity from the network map.
|
||||
Party notary = getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
|
||||
|
||||
// We create the transaction components.
|
||||
IOUState outputState = new IOUState(iouValue, getOurIdentity(), otherParty);
|
||||
StateAndContract outputContractAndState = new StateAndContract(outputState, IOUContract.ID);
|
||||
List<PublicKey> requiredSigners = ImmutableList.of(getOurIdentity().getOwningKey(), otherParty.getOwningKey());
|
||||
Command cmd = new Command<>(new IOUContract.Create(), requiredSigners);
|
||||
List<PublicKey> requiredSigners = Arrays.asList(getOurIdentity().getOwningKey(), otherParty.getOwningKey());
|
||||
Command command = new Command<>(new IOUContract.Create(), requiredSigners);
|
||||
|
||||
// We add the items to the builder.
|
||||
txBuilder.withItems(outputContractAndState, cmd);
|
||||
// We create a transaction builder and add the components.
|
||||
TransactionBuilder txBuilder = new TransactionBuilder(notary)
|
||||
.addOutputState(outputState, IOUContract.ID)
|
||||
.addCommand(command);
|
||||
|
||||
// Verifying the transaction.
|
||||
txBuilder.verify(getServiceHub());
|
||||
|
||||
// Signing the transaction.
|
||||
final SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder);
|
||||
SignedTransaction signedTx = getServiceHub().signInitialTransaction(txBuilder);
|
||||
|
||||
// Creating a session with the other party.
|
||||
FlowSession otherpartySession = initiateFlow(otherParty);
|
||||
FlowSession otherPartySession = initiateFlow(otherParty);
|
||||
|
||||
// Obtaining the counterparty's signature.
|
||||
SignedTransaction fullySignedTx = subFlow(new CollectSignaturesFlow(
|
||||
signedTx, ImmutableList.of(otherpartySession), CollectSignaturesFlow.tracker()));
|
||||
signedTx, Arrays.asList(otherPartySession), CollectSignaturesFlow.tracker()));
|
||||
|
||||
// Finalising the transaction.
|
||||
subFlow(new FinalityFlow(fullySignedTx));
|
||||
@ -78,4 +74,4 @@ public class IOUFlow extends FlowLogic<Void> {
|
||||
return null;
|
||||
// DOCEND 02
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
package net.corda.docs.java.tutorial.twoparty;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.corda.core.contracts.ContractState;
|
||||
import net.corda.core.identity.AbstractParty;
|
||||
import net.corda.core.identity.Party;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class IOUState implements ContractState {
|
||||
@ -32,6 +32,6 @@ public class IOUState implements ContractState {
|
||||
|
||||
@Override
|
||||
public List<AbstractParty> getParticipants() {
|
||||
return ImmutableList.of(lender, borrower);
|
||||
return Arrays.asList(lender, borrower);
|
||||
}
|
||||
}
|
@ -1,19 +1,22 @@
|
||||
@file:Suppress("MemberVisibilityCanBePrivate")
|
||||
|
||||
package net.corda.docs.tutorial.helloworld
|
||||
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import com.template.TemplateContract
|
||||
import net.corda.core.flows.FinalityFlow
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.InitiatingFlow
|
||||
import net.corda.core.flows.StartableByRPC
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
|
||||
// DOCSTART 01
|
||||
// Add these imports:
|
||||
import net.corda.core.contracts.Command
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
|
||||
// Replace TemplateFlow's definition with:
|
||||
// Replace Initiator's definition with:
|
||||
@InitiatingFlow
|
||||
@StartableByRPC
|
||||
class IOUFlow(val iouValue: Int,
|
||||
@ -30,12 +33,12 @@ class IOUFlow(val iouValue: Int,
|
||||
|
||||
// We create the transaction components.
|
||||
val outputState = IOUState(iouValue, ourIdentity, otherParty)
|
||||
val cmd = Command(TemplateContract.Commands.Action(), ourIdentity.owningKey)
|
||||
val command = Command(TemplateContract.Commands.Action(), ourIdentity.owningKey)
|
||||
|
||||
// We create a transaction builder and add the components.
|
||||
val txBuilder = TransactionBuilder(notary = notary)
|
||||
.addOutputState(outputState, TemplateContract.ID)
|
||||
.addCommand(cmd)
|
||||
.addCommand(command)
|
||||
|
||||
// We sign the transaction.
|
||||
val signedTx = serviceHub.signInitialTransaction(txBuilder)
|
@ -1,9 +1,11 @@
|
||||
@file:Suppress("MemberVisibilityCanBePrivate")
|
||||
|
||||
package net.corda.docs.tutorial.helloworld
|
||||
|
||||
import net.corda.core.contracts.ContractState
|
||||
|
||||
// DOCSTART 01
|
||||
// Add these imports:
|
||||
// Add this import:
|
||||
import net.corda.core.identity.Party
|
||||
|
||||
// Replace TemplateState's definition with:
|
||||
@ -12,4 +14,4 @@ class IOUState(val value: Int,
|
||||
val borrower: Party) : ContractState {
|
||||
override val participants get() = listOf(lender, borrower)
|
||||
}
|
||||
// DOCEND 01
|
||||
// DOCEND 01
|
@ -1,23 +0,0 @@
|
||||
package net.corda.docs.tutorial.helloworld
|
||||
|
||||
import net.corda.core.contracts.CommandData
|
||||
import net.corda.core.contracts.Contract
|
||||
import net.corda.core.transactions.LedgerTransaction
|
||||
|
||||
open class TemplateContract : Contract {
|
||||
// This is used to identify our contract when building a transaction.
|
||||
companion object {
|
||||
val ID = "com.template.TemplateContract"
|
||||
}
|
||||
|
||||
// A transaction is considered valid if the verify() function of the contract of each of the transaction's input
|
||||
// and output states does not throw an exception.
|
||||
override fun verify(tx: LedgerTransaction) {
|
||||
// Verification logic goes here.
|
||||
}
|
||||
|
||||
// Used to indicate the transaction's intent.
|
||||
interface Commands : CommandData {
|
||||
class Action : Commands
|
||||
}
|
||||
}
|
@ -5,15 +5,14 @@ import net.corda.core.contracts.Contract
|
||||
import net.corda.core.transactions.LedgerTransaction
|
||||
|
||||
// DOCSTART 01
|
||||
// Add these imports:
|
||||
// Add this import:
|
||||
import net.corda.core.contracts.*
|
||||
|
||||
// Replace IOUContract's contract ID and definition with:
|
||||
class IOUContract : Contract {
|
||||
companion object {
|
||||
val ID = "com.template.IOUContract"
|
||||
const val ID = "com.template.IOUContract"
|
||||
}
|
||||
|
||||
|
||||
// Our Create command.
|
||||
class Create : CommandData
|
||||
|
||||
@ -26,15 +25,15 @@ class IOUContract : Contract {
|
||||
"There should be one output state of type IOUState." using (tx.outputs.size == 1)
|
||||
|
||||
// IOU-specific constraints.
|
||||
val out = tx.outputsOfType<IOUState>().single()
|
||||
"The IOU's value must be non-negative." using (out.value > 0)
|
||||
"The lender and the borrower cannot be the same entity." using (out.lender != out.borrower)
|
||||
val output = tx.outputsOfType<IOUState>().single()
|
||||
"The IOU's value must be non-negative." using (output.value > 0)
|
||||
"The lender and the borrower cannot be the same entity." using (output.lender != output.borrower)
|
||||
|
||||
// Constraints on the signers.
|
||||
val expectedSigners = listOf(output.borrower.owningKey, output.lender.owningKey)
|
||||
"There must be two signers." using (command.signers.toSet().size == 2)
|
||||
"The borrower and lender must be signers." using (command.signers.containsAll(listOf(
|
||||
out.borrower.owningKey, out.lender.owningKey)))
|
||||
"The borrower and lender must be signers." using (command.signers.containsAll(expectedSigners))
|
||||
}
|
||||
}
|
||||
}
|
||||
// DOCEND 01
|
||||
// DOCEND 01
|
@ -1,21 +1,18 @@
|
||||
@file:Suppress("MemberVisibilityCanBePrivate")
|
||||
|
||||
package net.corda.docs.tutorial.twoparty
|
||||
|
||||
// DOCSTART 01
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.core.contracts.Command
|
||||
import net.corda.core.contracts.StateAndContract
|
||||
import net.corda.core.flows.*
|
||||
import net.corda.core.flows.CollectSignaturesFlow
|
||||
import net.corda.core.flows.FinalityFlow
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.InitiatingFlow
|
||||
import net.corda.core.flows.StartableByRPC
|
||||
import net.corda.core.identity.Party
|
||||
import net.corda.core.messaging.CordaRPCOps
|
||||
import net.corda.core.serialization.SerializationWhitelist
|
||||
import net.corda.core.transactions.TransactionBuilder
|
||||
import net.corda.core.utilities.ProgressTracker
|
||||
import java.util.function.Function
|
||||
import javax.ws.rs.GET
|
||||
import javax.ws.rs.Path
|
||||
import javax.ws.rs.Produces
|
||||
import javax.ws.rs.core.MediaType
|
||||
import javax.ws.rs.core.Response
|
||||
// DOCEND 01
|
||||
|
||||
@InitiatingFlow
|
||||
@ -29,20 +26,18 @@ class IOUFlow(val iouValue: Int,
|
||||
/** The flow logic is encapsulated within the call() method. */
|
||||
@Suspendable
|
||||
override fun call() {
|
||||
// DOCSTART 02
|
||||
// We retrieve the notary identity from the network map.
|
||||
val notary = serviceHub.networkMapCache.notaryIdentities[0]
|
||||
|
||||
// DOCSTART 02
|
||||
// We create a transaction builder.
|
||||
val txBuilder = TransactionBuilder(notary = notary)
|
||||
|
||||
// We create the transaction components.
|
||||
val outputState = IOUState(iouValue, ourIdentity, otherParty)
|
||||
val outputContractAndState = StateAndContract(outputState, IOUContract.ID)
|
||||
val cmd = Command(IOUContract.Create(), listOf(ourIdentity.owningKey, otherParty.owningKey))
|
||||
val command = Command(IOUContract.Create(), listOf(ourIdentity.owningKey, otherParty.owningKey))
|
||||
|
||||
// We add the items to the builder.
|
||||
txBuilder.withItems(outputContractAndState, cmd)
|
||||
// We create a transaction builder and add the components.
|
||||
val txBuilder = TransactionBuilder(notary = notary)
|
||||
.addOutputState(outputState, IOUContract.ID)
|
||||
.addCommand(command)
|
||||
|
||||
// Verifying the transaction.
|
||||
txBuilder.verify(serviceHub)
|
||||
@ -51,10 +46,10 @@ class IOUFlow(val iouValue: Int,
|
||||
val signedTx = serviceHub.signInitialTransaction(txBuilder)
|
||||
|
||||
// Creating a session with the other party.
|
||||
val otherpartySession = initiateFlow(otherParty)
|
||||
val otherPartySession = initiateFlow(otherParty)
|
||||
|
||||
// Obtaining the counterparty's signature.
|
||||
val fullySignedTx = subFlow(CollectSignaturesFlow(signedTx, listOf(otherpartySession), CollectSignaturesFlow.tracker()))
|
||||
val fullySignedTx = subFlow(CollectSignaturesFlow(signedTx, listOf(otherPartySession), CollectSignaturesFlow.tracker()))
|
||||
|
||||
// Finalising the transaction.
|
||||
subFlow(FinalityFlow(fullySignedTx))
|
@ -1,10 +1,9 @@
|
||||
@file:Suppress("unused")
|
||||
|
||||
package net.corda.docs.tutorial.twoparty
|
||||
|
||||
import co.paralleluniverse.fibers.Suspendable
|
||||
import net.corda.core.flows.FlowLogic
|
||||
import net.corda.core.flows.FlowSession
|
||||
import net.corda.core.flows.InitiatedBy
|
||||
import net.corda.core.flows.SignTransactionFlow
|
||||
import net.corda.core.flows.*
|
||||
import net.corda.docs.tutorial.helloworld.IOUFlow
|
||||
import net.corda.docs.tutorial.helloworld.IOUState
|
||||
|
||||
@ -30,4 +29,4 @@ class IOUFlowResponder(val otherPartySession: FlowSession) : FlowLogic<Unit>() {
|
||||
subFlow(signTransactionFlow)
|
||||
}
|
||||
}
|
||||
// DOCEND 01
|
||||
// DOCEND 01
|
Reference in New Issue
Block a user