Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Progress Trackers #59

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,70 @@ import net.corda.core.flows.InitiatedBy
import net.corda.core.flows.InitiatingFlow
import net.corda.core.identity.Party
import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.ProgressTracker


object ConfidentialIssueFlow {
@InitiatingFlow
class Initiator<T : TokenType>(
val token: T,
val holder: Party,
val notary: Party,
val amount: Amount<T>? = null
val amount: Amount<T>? = null,
override val progressTracker: ProgressTracker = tracker()
) : FlowLogic<SignedTransaction>() {

@Suspendable
override fun call(): SignedTransaction {
val holderSession = initiateFlow(holder)
progressTracker.currentStep = REQUESTING_IDENTITY
val confidentialHolder = subFlow(RequestConfidentialIdentity.Initiator(holderSession)).party.anonymise()
return subFlow(IssueToken.Initiator(token, confidentialHolder, notary, amount, holderSession))
progressTracker.currentStep = ISSUING_TOKEN
return subFlow(IssueToken.Initiator(
token,
confidentialHolder,
notary,
amount,
holderSession,
progressTracker = ISSUING_TOKEN.childProgressTracker()
))
}

companion object {
object REQUESTING_IDENTITY : ProgressTracker.Step("Requesting a confidential identity.")

object ISSUING_TOKEN : ProgressTracker.Step("Issuing token.") {
override fun childProgressTracker() = IssueToken.Initiator.tracker()
}

fun tracker() = ProgressTracker(REQUESTING_IDENTITY, ISSUING_TOKEN)
}
}

@InitiatedBy(Initiator::class)
class Responder(val otherSession: FlowSession) : FlowLogic<Unit>() {
class Responder(
val otherSession: FlowSession,
override val progressTracker: ProgressTracker = tracker()
) : FlowLogic<Unit>() {

constructor(otherSession: FlowSession) : this(otherSession, tracker())

@Suspendable
override fun call() {
progressTracker.currentStep = REQUESTING_IDENTITY
subFlow(RequestConfidentialIdentity.Responder(otherSession))
subFlow(IssueToken.Responder(otherSession))
progressTracker.currentStep = ISSUING_TOKEN
subFlow(IssueToken.Responder(otherSession, progressTracker = ISSUING_TOKEN.childProgressTracker()))
}

companion object {
object REQUESTING_IDENTITY : ProgressTracker.Step("Requesting a confidential identity.")

object ISSUING_TOKEN : ProgressTracker.Step("Issuing token.") {
override fun childProgressTracker() = IssueToken.Responder.tracker()
}

fun tracker() = ProgressTracker(REQUESTING_IDENTITY, ISSUING_TOKEN)
}
}
}
Expand All @@ -41,26 +82,60 @@ object ConfidentialMoveFlow {
class Initiator<T : TokenType>(
val ownedToken: T,
val holder: Party,
val amount: Amount<T>? = null
val amount: Amount<T>? = null,
override val progressTracker: ProgressTracker = tracker()
) : FlowLogic<SignedTransaction>() {

@Suspendable
override fun call(): SignedTransaction {
val holderSession = initiateFlow(holder)
progressTracker.currentStep = REQUESTING_IDENTITY
val confidentialHolder = subFlow(RequestConfidentialIdentity.Initiator(holderSession)).party.anonymise()
progressTracker.currentStep = MOVING_TOKEN
return if (amount == null) {
subFlow(MoveTokenNonFungible(ownedToken, holder, holderSession))
subFlow(MoveTokenNonFungible(ownedToken, holder, holderSession, progressTracker = MOVING_TOKEN.childProgressTracker()))
} else {
subFlow(MoveTokenFungible(amount, confidentialHolder, holderSession))
subFlow(MoveTokenFungible(amount, confidentialHolder, holderSession, progressTracker = MOVING_TOKEN.childProgressTracker()))
}
}

companion object {
object REQUESTING_IDENTITY : ProgressTracker.Step("Requesting a confidential identity.")

object MOVING_TOKEN : ProgressTracker.Step("Moving token.") {
override fun childProgressTracker() = MoveToken.Initiator.tracker()
}

fun tracker() = ProgressTracker(REQUESTING_IDENTITY, MOVING_TOKEN)
}

}

@InitiatedBy(Initiator::class)
class Responder(val otherSession: FlowSession) : FlowLogic<Unit>() {
class Responder(
val otherSession: FlowSession,
override val progressTracker: ProgressTracker = tracker()
) : FlowLogic<Unit>() {

constructor(otherSession: FlowSession) : this(otherSession, tracker())

@Suspendable
override fun call() {
progressTracker.currentStep = REQUESTING_IDENTITY
subFlow(RequestConfidentialIdentity.Responder(otherSession))
subFlow(MoveToken.Responder(otherSession))
progressTracker.currentStep = MOVING_TOKEN
subFlow(MoveToken.Responder(otherSession, progressTracker = MOVING_TOKEN.childProgressTracker()))
}

companion object {
object REQUESTING_IDENTITY : ProgressTracker.Step("Requesting a confidential identity.")

object MOVING_TOKEN : ProgressTracker.Step("Moving token.") {
override fun childProgressTracker() = MoveToken.Responder.tracker()
}

fun tracker() = ProgressTracker(REQUESTING_IDENTITY, MOVING_TOKEN)
}

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,19 @@ class CreateEvolvableToken<T : EvolvableTokenType>(

object SIGNING : ProgressTracker.Step("Signing transaction proposal.")

object NOTIFYING_MAINTAINERS : ProgressTracker.Step("Notifying all maintainers.")

object COLLECTING : ProgressTracker.Step("Gathering counterparty signature.") {
override fun childProgressTracker() = CollectSignaturesFlow.tracker()
}

object NOTIFYING_OBSERVERS : ProgressTracker.Step("Notifying all observers.")

object RECORDING : ProgressTracker.Step("Recording signed transaction.") {
override fun childProgressTracker() = FinalityFlow.tracker()
}

fun tracker() = ProgressTracker(CREATING, SIGNING, COLLECTING, RECORDING)
fun tracker() = ProgressTracker(CREATING, SIGNING, NOTIFYING_MAINTAINERS, COLLECTING, NOTIFYING_OBSERVERS, RECORDING)
}

override val progressTracker: ProgressTracker = tracker()
Expand All @@ -60,20 +64,26 @@ class CreateEvolvableToken<T : EvolvableTokenType>(
progressTracker.currentStep = SIGNING
val stx: SignedTransaction = serviceHub.signInitialTransaction(utx)

// Gather signatures from other maintainers
progressTracker.currentStep = COLLECTING
// Notify maintainers of proposed transaction
progressTracker.currentStep = NOTIFYING_MAINTAINERS
val otherMaintainerSessions = otherMaintainers().map { initiateFlow(it) }
otherMaintainerSessions.forEach { it.send(Notification(signatureRequired = true)) }

// Gather signatures from other maintainers
progressTracker.currentStep = COLLECTING
val tx = subFlow(CollectSignaturesFlow(
partiallySignedTx = stx,
sessionsToCollectFrom = otherMaintainerSessions,
progressTracker = COLLECTING.childProgressTracker()
))

// Finalise with all participants, including maintainers, participants, and subscribers (via distribution list)
progressTracker.currentStep = RECORDING
// Notify all observers (non-maintainers) of proposed transaction
progressTracker.currentStep = NOTIFYING_OBSERVERS
val observerSessions = wellKnownObservers().map { initiateFlow(it) }
observerSessions.forEach { it.send(Notification(signatureRequired = false)) }

// Finalise with all participants, including maintainers, participants, and subscribers (via distribution list)
progressTracker.currentStep = RECORDING
return subFlow(FinalityFlow(
transaction = tx,
sessions = (otherMaintainerSessions + observerSessions),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,47 @@
package com.r3.corda.sdk.token.workflow.flows

import co.paralleluniverse.fibers.Suspendable
import net.corda.core.contracts.requireThat
import net.corda.core.flows.*
import net.corda.core.node.StatesToRecord
import net.corda.core.transactions.SignedTransaction
import net.corda.core.utilities.ProgressTracker
import net.corda.core.utilities.unwrap

@InitiatedBy(CreateEvolvableToken::class)
class CreateEvolvableTokenResponder(val otherSession: FlowSession) : FlowLogic<SignedTransaction>() {

companion object {
object PREPARING : ProgressTracker.Step("Preparing for evolvable token creation transaction.")

object SIGNING : ProgressTracker.Step("Signing transaction proposal.") {
override fun childProgressTracker() = SignTransactionFlow.tracker()
}

object RECORDING : ProgressTracker.Step("Recording signed transaction.")

fun tracker() = ProgressTracker(PREPARING, SIGNING, RECORDING)
}

override val progressTracker: ProgressTracker = tracker()


@Suspendable
override fun call(): SignedTransaction {
// Receive the notification
progressTracker.currentStep = PREPARING
val notification = otherSession.receive<CreateEvolvableToken.Notification>().unwrap { it }

// Sign the transaction proposal, if required
if (notification.signatureRequired) {
val signTransactionFlow = object : SignTransactionFlow(otherSession) {
override fun checkTransaction(stx: SignedTransaction) = requireThat {
// TODO
}
progressTracker.currentStep = SIGNING
val signTransactionFlow = object : SignTransactionFlow(otherSession, progressTracker = SIGNING.childProgressTracker()) {
override fun checkTransaction(stx: SignedTransaction) = Unit
}
subFlow(signTransactionFlow)
}

// Resolve the creation transaction.
progressTracker.currentStep = RECORDING
return subFlow(ReceiveFinalityFlow(otherSideSession = otherSession, statesToRecord = StatesToRecord.ONLY_RELEVANT))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ object IssueToken {
val issueTo: AbstractParty,
val notary: Party,
val amount: Amount<T>? = null,
val session: FlowSession? = null
val session: FlowSession? = null,
override val progressTracker: ProgressTracker = tracker()
) : FlowLogic<SignedTransaction>() {
companion object {
object DIST_LIST : ProgressTracker.Step("Adding party to distribution list.")
Expand All @@ -74,8 +75,6 @@ object IssueToken {
fun tracker() = ProgressTracker(DIST_LIST, SIGNING, RECORDING)
}

override val progressTracker: ProgressTracker = tracker()

@Suspendable
override fun call(): SignedTransaction {
// This is the identity which will be used to issue tokens.
Expand Down Expand Up @@ -124,17 +123,30 @@ object IssueToken {
// Can issue to yourself, but finality flow doesn't take a session then.
val sessions = if (me == holderParty) emptyList() else listOf(holderSession)
return subFlow(FinalityFlow(transaction = stx,
progressTracker = RECORDING.childProgressTracker(),
sessions = sessions
sessions = sessions,
progressTracker = RECORDING.childProgressTracker()
))
}
}

@InitiatedBy(Initiator::class)
class Responder(val otherSession: FlowSession) : FlowLogic<Unit>() {
class Responder(
val otherSession: FlowSession,
override val progressTracker: ProgressTracker = tracker()
) : FlowLogic<Unit>() {

constructor(otherSession: FlowSession) : this(otherSession, tracker())

companion object {
object RECORDING : ProgressTracker.Step("Recording token issuance transaction.")

fun tracker() = ProgressTracker(RECORDING)
}

@Suspendable
override fun call() {
// We must do this check because FinalityFlow does not send locally and we want to be able to issue to ourselves.
progressTracker.currentStep = RECORDING
if (!serviceHub.myInfo.isLegalIdentity(otherSession.counterparty)) {
// Resolve the issuance transaction.
subFlow(ReceiveFinalityFlow(otherSideSession = otherSession, statesToRecord = StatesToRecord.ONLY_RELEVANT))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,7 @@ import com.r3.corda.sdk.token.contracts.types.TokenType
import com.r3.corda.sdk.token.workflow.selection.TokenSelection
import com.r3.corda.sdk.token.workflow.selection.generateMoveNonFungible
import net.corda.core.contracts.Amount
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.StartableByRPC
import net.corda.core.flows.*
import net.corda.core.identity.AbstractParty
import net.corda.core.node.StatesToRecord
import net.corda.core.transactions.SignedTransaction
Expand All @@ -27,7 +21,8 @@ object MoveToken {
abstract class Initiator<T : TokenType>(
val token: T,
val holder: AbstractParty,
val session: FlowSession? = null
val session: FlowSession? = null,
override val progressTracker: ProgressTracker = tracker()
) : FlowLogic<SignedTransaction>() {
companion object {
object GENERATE_MOVE : ProgressTracker.Step("Generating tokens move.")
Expand All @@ -39,8 +34,6 @@ object MoveToken {
fun tracker() = ProgressTracker(GENERATE_MOVE, SIGNING, RECORDING)
}

override val progressTracker: ProgressTracker = tracker()

@Suspendable
abstract fun generateMove(): Pair<TransactionBuilder, List<PublicKey>>

Expand Down Expand Up @@ -70,22 +63,36 @@ object MoveToken {
}

@InitiatedBy(Initiator::class)
class Responder(val otherSession: FlowSession) : FlowLogic<Unit>() {
class Responder(
val otherSession: FlowSession,
override val progressTracker: ProgressTracker = tracker()
) : FlowLogic<Unit>() {

constructor(otherSession: FlowSession) : this(otherSession, tracker())

@Suspendable
override fun call() {
// Resolve the move transaction.
progressTracker.currentStep = RECORDING
if (!serviceHub.myInfo.isLegalIdentity(otherSession.counterparty)) {
subFlow(ReceiveFinalityFlow(otherSideSession = otherSession, statesToRecord = StatesToRecord.ONLY_RELEVANT))
}
}

companion object {
object RECORDING : ProgressTracker.Step("Recording token movement transaction.")

fun tracker() = ProgressTracker(RECORDING)
}
}
}

class MoveTokenNonFungible<T : TokenType>(
val ownedToken: T,
holder: AbstractParty,
session: FlowSession? = null
) : MoveToken.Initiator<T>(ownedToken, holder, session) {
session: FlowSession? = null,
progressTracker: ProgressTracker = tracker()
) : MoveToken.Initiator<T>(ownedToken, holder, session, progressTracker) {
@Suspendable
override fun generateMove(): Pair<TransactionBuilder, List<PublicKey>> {
return generateMoveNonFungible(serviceHub.vaultService, ownedToken, holder)
Expand All @@ -95,8 +102,9 @@ class MoveTokenNonFungible<T : TokenType>(
open class MoveTokenFungible<T : TokenType>(
val amount: Amount<T>,
holder: AbstractParty,
session: FlowSession? = null
) : MoveToken.Initiator<T>(amount.token, holder, session) {
session: FlowSession? = null,
progressTracker: ProgressTracker = tracker()
) : MoveToken.Initiator<T>(amount.token, holder, session, progressTracker) {
@Suspendable
override fun generateMove(): Pair<TransactionBuilder, List<PublicKey>> {
val tokenSelection = TokenSelection(serviceHub)
Expand Down
Loading