From 9f4897f7c4debc4497cb2367459365a52d5e5e39 Mon Sep 17 00:00:00 2001
From: Mike Hearn <mike@r3cev.com>
Date: Fri, 12 Feb 2016 15:49:18 +0100
Subject: [PATCH] Simplifies two-party trade protocol to return
 SignedTransaction instead of a pair of other forms.

---
 docs/source/protocol-state-machines.rst       | 28 +++++++++----------
 .../protocols/TwoPartyTradeProtocol.kt        | 27 +++++++++---------
 src/main/kotlin/core/node/TraderDemo.kt       |  4 +--
 .../messaging/TwoPartyTradeProtocolTests.kt   |  6 ++--
 4 files changed, 32 insertions(+), 33 deletions(-)

diff --git a/docs/source/protocol-state-machines.rst b/docs/source/protocol-state-machines.rst
index 578b1afe0d..1cd7724e50 100644
--- a/docs/source/protocol-state-machines.rst
+++ b/docs/source/protocol-state-machines.rst
@@ -111,7 +111,7 @@ each side.
 
           fun runSeller(smm: StateMachineManager, timestampingAuthority: LegallyIdentifiableNode,
                         otherSide: SingleMessageRecipient, assetToSell: StateAndRef<OwnableState>, price: Amount,
-                        myKeyPair: KeyPair, buyerSessionID: Long): ListenableFuture<Pair<WireTransaction, LedgerTransaction>> {
+                        myKeyPair: KeyPair, buyerSessionID: Long): ListenableFuture<SignedTransaction> {
               val seller = Seller(otherSide, timestampingAuthority, assetToSell, price, myKeyPair, buyerSessionID)
               smm.add("$TRADE_TOPIC.seller", seller)
               return seller.resultFuture
@@ -119,7 +119,7 @@ each side.
 
           fun runBuyer(smm: StateMachineManager, timestampingAuthority: LegallyIdentifiableNode,
                        otherSide: SingleMessageRecipient, acceptablePrice: Amount, typeToBuy: Class<out OwnableState>,
-                       sessionID: Long): ListenableFuture<Pair<WireTransaction, LedgerTransaction>> {
+                       sessionID: Long): ListenableFuture<SignedTransaction> {
               val buyer = Buyer(otherSide, timestampingAuthority.identity, acceptablePrice, typeToBuy, sessionID)
               smm.add("$TRADE_TOPIC.buyer", buyer)
               return buyer.resultFuture
@@ -140,9 +140,9 @@ each side.
                        val assetToSell: StateAndRef<OwnableState>,
                        val price: Amount,
                        val myKeyPair: KeyPair,
-                       val buyerSessionID: Long) : ProtocolStateMachine<Pair<WireTransaction, LedgerTransaction>>() {
+                       val buyerSessionID: Long) : ProtocolStateMachine<SignedTransaction>() {
               @Suspendable
-              override fun call(): Pair<WireTransaction, LedgerTransaction> {
+              override fun call(): SignedTransaction {
                   TODO()
               }
           }
@@ -156,9 +156,9 @@ each side.
                       val timestampingAuthority: Party,
                       val acceptablePrice: Amount,
                       val typeToBuy: Class<out OwnableState>,
-                      val sessionID: Long) : ProtocolStateMachine<Pair<WireTransaction, LedgerTransaction>>() {
+                      val sessionID: Long) : ProtocolStateMachine<SignedTransaction>() {
               @Suspendable
-              override fun call(): Pair<WireTransaction, LedgerTransaction> {
+              override fun call(): SignedTransaction {
                   TODO()
               }
           }
@@ -251,9 +251,9 @@ Let's implement the ``Seller.call`` method. This will be invoked by the platform
       val ourSignature = signWithOurKey(partialTX)
       val tsaSig = timestamp(partialTX)
 
-      val ledgerTX = sendSignatures(partialTX, ourSignature, tsaSig)
+      val stx: SignedTransaction = sendSignatures(partialTX, ourSignature, tsaSig)
 
-      return Pair(partialTX.tx, ledgerTX)
+      return stx
 
 Here we see the outline of the procedure. We receive a proposed trade transaction from the buyer and check that it's
 valid. Then we sign with our own key, request a timestamping authority to assert with another signature that the
@@ -338,16 +338,16 @@ Here's the rest of the code:
 
       @Suspendable
       open fun sendSignatures(partialTX: SignedTransaction, ourSignature: DigitalSignature.WithKey,
-                              tsaSig: DigitalSignature.LegallyIdentifiable): LedgerTransaction {
+                              tsaSig: DigitalSignature.LegallyIdentifiable): SignedTransaction {
           val fullySigned = partialTX + tsaSig + ourSignature
-          val ltx = fullySigned.verifyToLedgerTransaction(serviceHub.identityService)
+          fullySigned.verify()
 
           // TODO: We should run it through our full TransactionGroup of all transactions here.
 
           logger.trace { "Built finished transaction, sending back to secondary!" }
 
           send(TRADE_TOPIC, otherSide, buyerSessionID, SignaturesFromSeller(tsaSig, ourSignature))
-          return ltx
+          return fullySigned
       }
 
 It's should be all pretty straightforward: here, ``txBits`` is the raw byte array representing the transaction.
@@ -372,7 +372,7 @@ OK, let's do the same for the buyer side:
    .. sourcecode:: kotlin
 
       @Suspendable
-      override fun call(): Pair<WireTransaction, LedgerTransaction> {
+      override fun call(): SignedTransaction {
           val tradeRequest = receiveAndValidateTradeRequest()
           val (ptx, cashSigningPubKeys) = assembleSharedTX(tradeRequest)
           val stx = signWithOurKeys(cashSigningPubKeys, ptx)
@@ -380,10 +380,10 @@ OK, let's do the same for the buyer side:
 
           logger.trace { "Got signatures from seller, verifying ... "}
           val fullySigned = stx + signatures.timestampAuthoritySig + signatures.sellerSig
-          val ltx = fullySigned.verifyToLedgerTransaction(serviceHub.identityService)
+          fullySigned.verify()
 
           logger.trace { "Fully signed transaction was valid. Trade complete! :-)" }
-          return Pair(fullySigned.tx, ltx)
+          return fullySigned
       }
 
       @Suspendable
diff --git a/src/main/kotlin/contracts/protocols/TwoPartyTradeProtocol.kt b/src/main/kotlin/contracts/protocols/TwoPartyTradeProtocol.kt
index e825d7cd86..2d8a65fd06 100644
--- a/src/main/kotlin/contracts/protocols/TwoPartyTradeProtocol.kt
+++ b/src/main/kotlin/contracts/protocols/TwoPartyTradeProtocol.kt
@@ -53,7 +53,7 @@ object TwoPartyTradeProtocol {
 
     fun runSeller(smm: StateMachineManager, timestampingAuthority: LegallyIdentifiableNode,
                   otherSide: SingleMessageRecipient, assetToSell: StateAndRef<OwnableState>, price: Amount,
-                  myKeyPair: KeyPair, buyerSessionID: Long): ListenableFuture<Pair<WireTransaction, LedgerTransaction>> {
+                  myKeyPair: KeyPair, buyerSessionID: Long): ListenableFuture<SignedTransaction> {
         val seller = Seller(otherSide, timestampingAuthority, assetToSell, price, myKeyPair, buyerSessionID)
         smm.add("$TRADE_TOPIC.seller", seller)
         return seller.resultFuture
@@ -61,7 +61,7 @@ object TwoPartyTradeProtocol {
 
     fun runBuyer(smm: StateMachineManager, timestampingAuthority: LegallyIdentifiableNode,
                  otherSide: SingleMessageRecipient, acceptablePrice: Amount, typeToBuy: Class<out OwnableState>,
-                 sessionID: Long): ListenableFuture<Pair<WireTransaction, LedgerTransaction>> {
+                 sessionID: Long): ListenableFuture<SignedTransaction> {
         val buyer = Buyer(otherSide, timestampingAuthority.identity, acceptablePrice, typeToBuy, sessionID)
         smm.add("$TRADE_TOPIC.buyer", buyer)
         return buyer.resultFuture
@@ -82,18 +82,18 @@ object TwoPartyTradeProtocol {
                       val assetToSell: StateAndRef<OwnableState>,
                       val price: Amount,
                       val myKeyPair: KeyPair,
-                      val buyerSessionID: Long) : ProtocolStateMachine<Pair<WireTransaction, LedgerTransaction>>() {
+                      val buyerSessionID: Long) : ProtocolStateMachine<SignedTransaction>() {
         @Suspendable
-        override fun call(): Pair<WireTransaction, LedgerTransaction> {
+        override fun call(): SignedTransaction {
             val partialTX: SignedTransaction = receiveAndCheckProposedTransaction()
 
             // These two steps could be done in parallel, in theory. Our framework doesn't support that yet though.
             val ourSignature = signWithOurKey(partialTX)
             val tsaSig = timestamp(partialTX)
 
-            val ledgerTX = sendSignatures(partialTX, ourSignature, tsaSig)
+            val signedTransaction = sendSignatures(partialTX, ourSignature, tsaSig)
 
-            return Pair(partialTX.tx, ledgerTX)
+            return signedTransaction
         }
 
         @Suspendable
@@ -136,16 +136,15 @@ object TwoPartyTradeProtocol {
 
         @Suspendable
         open fun sendSignatures(partialTX: SignedTransaction, ourSignature: DigitalSignature.WithKey,
-                                tsaSig: DigitalSignature.LegallyIdentifiable): LedgerTransaction {
+                                tsaSig: DigitalSignature.LegallyIdentifiable): SignedTransaction {
             val fullySigned = partialTX + tsaSig + ourSignature
-            val ltx = fullySigned.verifyToLedgerTransaction(serviceHub.identityService)
 
             // TODO: We should run it through our full TransactionGroup of all transactions here.
 
             logger.trace { "Built finished transaction, sending back to secondary!" }
 
             send(TRADE_TOPIC, otherSide, buyerSessionID, SignaturesFromSeller(tsaSig, ourSignature))
-            return ltx
+            return fullySigned
         }
     }
 
@@ -158,9 +157,9 @@ object TwoPartyTradeProtocol {
                      val timestampingAuthority: Party,
                      val acceptablePrice: Amount,
                      val typeToBuy: Class<out OwnableState>,
-                     val sessionID: Long) : ProtocolStateMachine<Pair<WireTransaction, LedgerTransaction>>() {
+                     val sessionID: Long) : ProtocolStateMachine<SignedTransaction>() {
         @Suspendable
-        override fun call(): Pair<WireTransaction, LedgerTransaction> {
+        override fun call(): SignedTransaction {
             val tradeRequest = receiveAndValidateTradeRequest()
             val (ptx, cashSigningPubKeys) = assembleSharedTX(tradeRequest)
             val stx = signWithOurKeys(cashSigningPubKeys, ptx)
@@ -168,10 +167,10 @@ object TwoPartyTradeProtocol {
 
             logger.trace { "Got signatures from seller, verifying ... "}
             val fullySigned = stx + signatures.timestampAuthoritySig + signatures.sellerSig
-            val ltx = fullySigned.verifyToLedgerTransaction(serviceHub.identityService)
+            fullySigned.verify()
 
-            logger.trace { "Fully signed transaction was valid. Trade complete! :-)" }
-            return Pair(fullySigned.tx, ltx)
+            logger.trace { "Signatures received are valid. Trade complete! :-)" }
+            return fullySigned
         }
 
         @Suspendable
diff --git a/src/main/kotlin/core/node/TraderDemo.kt b/src/main/kotlin/core/node/TraderDemo.kt
index 01c84d6fcd..5380c9c7d7 100644
--- a/src/main/kotlin/core/node/TraderDemo.kt
+++ b/src/main/kotlin/core/node/TraderDemo.kt
@@ -110,7 +110,7 @@ fun main(args: Array<String>) {
                 println()
                 println("Purchase complete - we are a happy customer! Final transaction is:")
                 println()
-                println(Emoji.renderIfSupported(it.first))
+                println(Emoji.renderIfSupported(it))
                 println()
                 println("Waiting for another seller to connect. Or press Ctrl-C to shut me down.")
             }
@@ -145,7 +145,7 @@ fun main(args: Array<String>) {
                 println()
                 println("Final transaction is")
                 println()
-                println(Emoji.renderIfSupported(it.first))
+                println(Emoji.renderIfSupported(it))
                 println()
                 node.stop()
             }
diff --git a/src/test/kotlin/core/messaging/TwoPartyTradeProtocolTests.kt b/src/test/kotlin/core/messaging/TwoPartyTradeProtocolTests.kt
index 312cecf61e..f1cdd3562f 100644
--- a/src/test/kotlin/core/messaging/TwoPartyTradeProtocolTests.kt
+++ b/src/test/kotlin/core/messaging/TwoPartyTradeProtocolTests.kt
@@ -88,7 +88,7 @@ class TwoPartyTradeProtocolTests : TestWithInMemoryNetwork() {
 
             assertEquals(aliceResult.get(), bobResult.get())
 
-            txns.add(aliceResult.get().first)
+            txns.add(aliceResult.get().tx)
             verify()
         }
     }
@@ -178,8 +178,8 @@ class TwoPartyTradeProtocolTests : TestWithInMemoryNetwork() {
             assertTrue(bobsNode.pump(false))
 
             // Bob is now finished and has the same transaction as Alice.
-            val tx = bobFuture.get()
-            txns.add(tx.first)
+            val stx = bobFuture.get()
+            txns.add(stx.tx)
             verify()
 
             assertTrue(smm.stateMachines.isEmpty())