<h2>A two party trading protocol<aclass="headerlink"href="#a-two-party-trading-protocol"title="Permalink to this headline">¶</a></h2>
<p>We would like to implement the “hello world” of shared transaction building protocols: a seller wishes to sell some
<em>asset</em> (e.g. some commercial paper) in return for <em>cash</em>. The buyer wishes to purchase the asset using his cash. They
want the trade to be atomic so neither side is exposed to the risk of settlement failure. We assume that the buyer
and seller have found each other and arranged the details on some exchange, or over the counter. The details of how
the trade is arranged isn’t covered in this article.</p>
<p>Our protocol has two parties (B and S for buyer and seller) and will proceed as follows:</p>
<olclass="arabic simple">
<li>S sends a <codeclass="docutils literal"><spanclass="pre">StateAndRef</span></code> pointing to the state they want to sell to B, along with info about the price they require
B to pay.</li>
<li>B sends to S a <codeclass="docutils literal"><spanclass="pre">SignedWireTransaction</span></code> that includes the state as input, B’s cash as input, the state with the new
owner key as output, and any change cash as output. It contains a single signature from B but isn’t valid because
it lacks a signature from S authorising movement of the asset.</li>
<li>S signs it and hands the now finalised <codeclass="docutils literal"><spanclass="pre">SignedWireTransaction</span></code> back to B.</li>
</ol>
<p>You can find the implementation of this protocol in the file <codeclass="docutils literal"><spanclass="pre">contracts/protocols/TwoPartyTradeProtocol.kt</span></code>.</p>
<p>Assuming no malicious termination, they both end the protocol being in posession of a valid, signed transaction that
represents an atomic asset swap.</p>
<p>Note that it’s the <em>seller</em> who initiates contact with the buyer, not vice-versa as you might imagine.</p>
<p>We start by defining an abstract base class to encapsulate the protocol. This is what code that invokes the protocol
will see:</p>
<divclass="codeset container">
<divclass="highlight-kotlin"><divclass="highlight"><pre>abstract class TwoPartyTradeProtocol {
class SellerInitialArgs(
val assetToSell: StateAndRef<OwnableState>,
val price: Amount,
val myKeyPair: KeyPair,
val buyerSessionID: Long
)
abstract fun runSeller(otherSide: SingleMessageRecipient, args: SellerInitialArgs): Seller
class BuyerInitialArgs(
val acceptablePrice: Amount,
val typeToBuy: Class<out OwnableState>,
val sessionID: Long
)
abstract fun runBuyer(otherSide: SingleMessageRecipient, args: BuyerInitialArgs): Buyer
abstract class Buyer : ProtocolStateMachine<BuyerInitialArgs, Pair<TimestampedWireTransaction, LedgerTransaction>>()
abstract class Seller : ProtocolStateMachine<SellerInitialArgs, Pair<TimestampedWireTransaction, LedgerTransaction>>()
companion object {
@JvmStatic fun create(smm: StateMachineManager): TwoPartyTradeProtocol {
return TwoPartyTradeProtocolImpl(smm)
}
}
}
</pre></div>
</div>
</div>
<p>Let’s unpack what this code does:</p>
<ulclass="simple">
<li>It defines a several classes nested inside the main <codeclass="docutils literal"><spanclass="pre">TwoPartyTradeProtocol</span></code> class, and a couple of methods, one to
run the buyer side of the protocol and one to run the seller side.</li>
<li>Two of the classes are simply wrappers for parameters to the trade; things like what is being sold, what the price
of the asset is, how much the buyer is willing to pay and so on. The <codeclass="docutils literal"><spanclass="pre">myKeyPair</span></code> field is simply the public key
that the seller wishes the buyer to send the cash to. The session ID field is sent from buyer to seller when the
<li>The other two classes define empty abstract classes called <codeclass="docutils literal"><spanclass="pre">Buyer</span></code> and <codeclass="docutils literal"><spanclass="pre">Seller</span></code>. These inherit from a class
called <codeclass="docutils literal"><spanclass="pre">ProtocolStateMachine</span></code> and provide two type parameters: the arguments class we just defined for each side
and the type of the object that the protocol finally produces (this doesn’t have to be identical for each side, even
though in this case it is).</li>
<li>Finally it simply defines a static method that creates an instance of an object that inherits from this base class
and returns it, with a <codeclass="docutils literal"><spanclass="pre">StateMachineManager</span></code> as an instance. The Impl class will be defined below.</li>
<p>Alright, so using this protocol shouldn’t be too hard: in the simplest case we can just pass in the details of the trade
to either runBuyer or runSeller, depending on who we are, and then call <codeclass="docutils literal"><spanclass="pre">.get()</span></code> on the resulting future to block the
calling thread until the protocol has finished. Or we could register a callback on the returned future that will be
invoked when it’s done, where we could e.g. update a user interface.</p>
<p>The only tricky part is how to get one of these things. We need a <codeclass="docutils literal"><spanclass="pre">StateMachineManager</span></code>. Where does that come from
<h2>The state machine manager<aclass="headerlink"href="#the-state-machine-manager"title="Permalink to this headline">¶</a></h2>
<p>The SMM is a class responsible for taking care of all running protocols in a node. It knows how to register handlers
with a <codeclass="docutils literal"><spanclass="pre">MessagingService</span></code> and iterate the right state machine when the time comes. It provides the
send/receive/sendAndReceive calls that let the code request network interaction and it will store a serialised copy of
each state machine before it’s suspended to wait for the network.</p>
<p>To get a <codeclass="docutils literal"><spanclass="pre">StateMachineManager</span></code>, you currently have to build one by passing in a <codeclass="docutils literal"><spanclass="pre">ServiceHub</span></code> and a thread or thread
pool which it can use. This will change in future so don’t worry about the details of this too much: just check the
unit tests to see how it’s done.</p>
</div>
<divclass="section"id="implementing-the-seller">
<h2>Implementing the seller<aclass="headerlink"href="#implementing-the-seller"title="Permalink to this headline">¶</a></h2>
<divclass="codeset container">
<divclass="highlight-kotlin"><divclass="highlight"><pre>private class TwoPartyTradeProtocolImpl(private val smm: StateMachineManager) : TwoPartyTradeProtocol() {
companion object {
val TRADE_TOPIC = "com.r3cev.protocols.trade"
}
class SellerImpl : Seller() {
override fun call(args: SellerInitialArgs): Pair<TimestampedWireTransaction, LedgerTransaction> {
TODO()
}
}
class BuyerImpl : Buyer() {
override fun call(args: BuyerInitialArgs): Pair<TimestampedWireTransaction, LedgerTransaction> {
TODO()
}
}
override fun runSeller(otherSide: SingleMessageRecipient, args: SellerInitialArgs): Seller {
<p>The runSeller and runBuyer methods simply start the state machines, passing in a reference to the classes and the topics
each side will use.</p>
<p>Now let’s try implementing the seller side. Firstly, we’re going to need a message to send to the buyer describing what
we want to trade. Remember: this data comes from whatever system was used to find the trading partner to begin with.
It could be as simple as a chat room or as complex as a 24/7 exchange.</p>
<divclass="codeset container">
<divclass="highlight-kotlin"><divclass="highlight"><pre><spanclass="c1">// This object is serialised to the network and is the first protocol message the seller sends to the buyer.</span>
<spanclass="n">logger</span><spanclass="p">().</span><spanclass="n">trace</span><spanclass="p">{</span><spanclass="s">"Received partially signed transaction"</span><spanclass="p">}</span>
</pre></div>
</div>
</div>
<p>That’s pretty straight forward. We generate a session ID to identify what’s happening on the seller side, fill out
the initial protocol message, and then call <codeclass="docutils literal"><spanclass="pre">sendAndReceive</span></code>. This function takes a few arguments:</p>
<ulclass="simple">
<li>A type argument, which is the object we’re expecting to receive from the other side.</li>
<li>The topic string that ensures the message is routed to the right bit of code in the other side’s node.</li>
<li>The session IDs that ensure the messages don’t get mixed up with other simultaneous trades.</li>
<li>And finally, the thing to send. It’ll be serialised and sent automatically.</li>
</ul>
<p>Once sendAndReceive is called, the call method will be suspended into a continuation. When it gets back we’ll do a log
message. The buyer is supposed to send us a transaction with all the right inputs/outputs/commands in return, with their
cash put into the transaction and their signature on it authorising the movement of the cash.</p>
<divclass="admonition note">
<pclass="first admonition-title">Note</p>
<p>There are a few rules you need to bear in mind when writing a class that will be used as a continuation.
The first is that anything on the stack when the function is suspended will be stored into the heap and kept alive by
the garbage collector. So try to avoid keeping enormous data structures alive unless you really have to.</p>
<p>The second is that as well as being kept on the heap, objects reachable from the stack will be serialised. The state
of the function call may be resurrected much later! Kryo doesn’t require objects be marked as serialisable, but even so,
doing things like creating threads from inside these calls would be a bad idea. They should only contain business
logic.</p>
<pclass="last">The third rule to bear in mind is that you can’t declare variables or methods in these classes and access
them from outside of the class, due to the bytecode rewriting and classloader tricks that are used to make this all
work. If you want access to something inside the BuyerImpl or SellerImpl classes, you must define a super-interface
or super-class (like <codeclass="docutils literal"><spanclass="pre">Buyer</span></code>/<codeclass="docutils literal"><spanclass="pre">Seller</span></code>) and put what you want to access there.</p>
<spanclass="s">"transaction sends us the right amount of cash"</span><spanclass="k">by</span><spanclass="p">(</span><spanclass="n">wtx</span><spanclass="p">.</span><spanclass="n">outputStates</span><spanclass="p">.</span><spanclass="n">sumCashBy</span><spanclass="p">(</span><spanclass="n">args</span><spanclass="p">.</span><spanclass="n">myKeyPair</span><spanclass="p">.</span><spanclass="k">public</span><spanclass="p">)</span><spanclass="p">==</span><spanclass="n">args</span><spanclass="p">.</span><spanclass="n">price</span><spanclass="p">)</span>
<spanclass="c1">// There are all sorts of funny games a malicious secondary might play here, we should fix them:</span>
<spanclass="c1">//</span>
<spanclass="c1">// - This tx may attempt to send some assets we aren't intending to sell to the secondary, if</span>
<spanclass="c1">// we're reusing keys! So don't reuse keys!</span>
<spanclass="c1">// - This tx may not be valid according to the contracts of the input states, so we must resolve</span>
<spanclass="c1">// and fully audit the transaction chains to convince ourselves that it is actually valid.</span>
<spanclass="c1">// - This tx may include output states that impose odd conditions on the movement of the cash,</span>
<spanclass="c1">// once we implement state pairing.</span>
<spanclass="c1">//</span>
<spanclass="c1">// but the goal of this code is not to be fully secure, but rather, just to find good ways to</span>
<spanclass="c1">// express protocol state machines on top of the messaging layer.</span>
<spanclass="n">logger</span><spanclass="p">().</span><spanclass="n">trace</span><spanclass="p">{</span><spanclass="s">"Built finished transaction, sending back to secondary!"</span><spanclass="p">}</span>
// Now sign the transaction with whatever keys we need to move the cash.
for (k in cashSigningPubKeys) {
val priv = serviceHub.keyManagementService.toPrivate(k)
ptx.signWith(KeyPair(k, priv))
}
val stx = ptx.toSignedTransaction(checkSufficientSignatures = false)
stx.verifySignatures() // Verifies that we generated a signed transaction correctly.
// TODO: Could run verify() here to make sure the only signature missing is the sellers.
logger().trace { "Sending partially signed transaction to seller" }
// TODO: Protect against the buyer terminating here and leaving us in the lurch without the final tx.
// TODO: Protect against a malicious buyer sending us back a different transaction to the one we built.
val fullySigned = sendAndReceive<TimestampedWireTransaction>(TRADE_TOPIC,
tradeRequest.sessionID, args.sessionID, stx)
logger().trace { "Got fully signed transaction, verifying ... "}
val ltx = fullySigned.verifyToLedgerTransaction(serviceHub.timestampingService, serviceHub.identityService)
logger().trace { "Fully signed transaction was valid. Trade complete! :-)" }
return Pair(fullySigned, ltx)
}
}
</pre></div>
</div>
</div>
<p>This code is fairly straightforward. Here are some things to pay attention to:</p>
<olclass="arabic simple">
<li>We do some sanity checking on the received message to ensure we’re being offered what we expected to be offered.</li>
<li>We create a cash spend in the normal way, by using <codeclass="docutils literal"><spanclass="pre">Cash().craftSpend</span></code>.</li>
<li>We access the <em>service hub</em> when we need it to access things that are transient and may change or be recreated
whilst a protocol is suspended, things like the wallet or the timestamping service. Remember that a protocol may
be suspended when it waits to receive a message across node or computer restarts, so objects representing a service
or data which may frequently change should be accessed ‘just in time’.</li>
<li>Finally, we send the unfinsished, invalid transaction to the seller so they can sign it. They are expected to send
back to us a <codeclass="docutils literal"><spanclass="pre">TimestampedWireTransaction</span></code>, which once we verify it, should be the final outcome of the trade.</li>
</ol>
<p>As you can see, the protocol logic is straightforward and does not contain any callbacks or network glue code, despite
the fact that it takes minimal resources and can survive node restarts.</p>
<divclass="admonition warning">
<pclass="first admonition-title">Warning</p>
<pclass="last">When accessing things via the <codeclass="docutils literal"><spanclass="pre">serviceHub</span></code> field, avoid the temptation to stuff a reference into a local variable.
If you do this then next time your protocol waits to receive an object, the system will try and serialise all your
local variables and end up trying to serialise, e.g. the timestamping service, which doesn’t make any conceptual
sense. The <codeclass="docutils literal"><spanclass="pre">serviceHub</span></code> field is defined by the <codeclass="docutils literal"><spanclass="pre">ProtocolStateMachine</span></code> superclass and is marked transient so
this problem doesn’t occur. It’s also restored for you after a protocol state machine is restored after a node
Built with <ahref="http://sphinx-doc.org/">Sphinx</a> using a <ahref="https://github.com/snide/sphinx_rtd_theme">theme</a> provided by <ahref="https://readthedocs.org">Read the Docs</a>.