diff --git a/docs/build/html/_sources/protocol-state-machines.txt b/docs/build/html/_sources/protocol-state-machines.txt index 21c34d4e66..69705fe896 100644 --- a/docs/build/html/_sources/protocol-state-machines.txt +++ b/docs/build/html/_sources/protocol-state-machines.txt @@ -57,7 +57,7 @@ Theory A *continuation* is a suspended stack frame stored in a regular object that can be passed around, serialised, unserialised and resumed from where it was suspended. This may sound abstract but don't worry, the examples below -will make it clearer. The JVM does not natively support continuations, so we implement them using a a library called +will make it clearer. The JVM does not natively support continuations, so we implement them using a library called JavaFlow which works through behind-the-scenes bytecode rewriting. You don't have to know how this works to benefit from it, however. @@ -150,12 +150,12 @@ Let's unpack what this code does: and returns it, with a ``StateMachineManager`` as an instance. The Impl class will be defined below. .. note:: Session IDs keep different traffic streams separated, so for security they must be large and random enough -to be unguessable. 63 bits is good enough. + to be unguessable. 63 bits is good enough. 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 ``.get()`` 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. +to either runBuyer or runSeller, depending on who we are, and then call ``.resultFuture.get()`` on resulting object 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. The only tricky part is how to get one of these things. We need a ``StateMachineManager``. Where does that come from and why do we need one? @@ -221,7 +221,8 @@ It could be as simple as a chat room or as complex as a 24/7 exchange. .. sourcecode:: kotlin - // This object is serialised to the network and is the first protocol message the seller sends to the buyer. + // This object is serialised to the network and is the first protocol message + // the seller sends to the buyer. class SellerTradeInfo( val assetForSale: StateAndRef, val price: Amount, @@ -244,11 +245,11 @@ Next we add some code to the ``SellerImpl.call`` method: // Make the first message we'll send to kick off the protocol. val hello = SellerTradeInfo(args.assetToSell, args.price, args.myKeyPair.public, sessionID) - // Zero is a special session ID that is being listened to by the buyer (i.e. before a session is started). - val partialTX = sendAndReceive(TRADE_TOPIC, args.buyerSessionID, sessionID, hello) + val partialTX = sendAndReceive(TRADE_TOPIC, args.buyerSessionID, + sessionID, hello) logger().trace { "Received partially signed transaction" } -That's pretty straight forward. We generate a session ID to identify what's happening on the seller side, fill out +That's pretty straightforward. We generate a session ID to identify what's happening on the seller side, fill out the initial protocol message, and then call ``sendAndReceive``. This function takes a few arguments: - A type argument, which is the object we're expecting to receive from the other side. @@ -347,16 +348,18 @@ OK, let's do the same for the buyer side: if (!args.typeToBuy.isInstance(tradeRequest.assetForSale.state)) throw AssetMismatchException(args.typeToBuy.name, assetTypeName) - // TODO: Either look up the stateref here in our local db, or accept a long chain of states and - // validate them to audit the other side and ensure it actually owns the state we are being offered! - // For now, just assume validity! + // TODO: Either look up the stateref here in our local db, or accept a long chain + // of states and validate them to audit the other side and ensure it actually owns + // the state we are being offered! For now, just assume validity! // Generate the shared transaction that both sides will sign, using the data we have. val ptx = PartialTransaction() - // Add input and output states for the movement of cash, by using the Cash contract to generate the states. + // Add input and output states for the movement of cash, by using the Cash contract + // to generate the states. val wallet = serviceHub.walletService.currentWallet val cashStates = wallet.statesOfType() - val cashSigningPubKeys = Cash().craftSpend(ptx, tradeRequest.price, tradeRequest.sellerOwnerKey, cashStates) + val cashSigningPubKeys = Cash().craftSpend(ptx, tradeRequest.price, + tradeRequest.sellerOwnerKey, cashStates) // Add inputs/outputs/a command for the movement of the asset. ptx.addInputState(tradeRequest.assetForSale.ref) // Just pick some new public key for now. @@ -378,14 +381,17 @@ OK, let's do the same for the buyer side: 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. + // 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(TRADE_TOPIC, tradeRequest.sessionID, args.sessionID, stx) logger().trace { "Got fully signed transaction, verifying ... "} - val ltx = fullySigned.verifyToLedgerTransaction(serviceHub.timestampingService, serviceHub.identityService) + val ltx = fullySigned.verifyToLedgerTransaction(serviceHub.timestampingService, + serviceHub.identityService) logger().trace { "Fully signed transaction was valid. Trade complete! :-)" } @@ -396,7 +402,8 @@ OK, let's do the same for the buyer side: This code is fairly straightforward. Here are some things to pay attention to: 1. We do some sanity checking on the received message to ensure we're being offered what we expected to be offered. -2. We create a cash spend in the normal way, by using ``Cash().craftSpend``. +2. We create a cash spend in the normal way, by using ``Cash().craftSpend``. See the contracts tutorial if this isn't + clear. 3. We access the *service hub* 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 @@ -411,6 +418,6 @@ the fact that it takes minimal resources and can survive node restarts. 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 ``serviceHub`` field is defined by the ``ProtocolStateMachine`` 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 + this problem doesn't occur. It's also restored for you when a protocol state machine is restored after a node restart. diff --git a/docs/build/html/protocol-state-machines.html b/docs/build/html/protocol-state-machines.html index 6748e8b774..141adaf286 100644 --- a/docs/build/html/protocol-state-machines.html +++ b/docs/build/html/protocol-state-machines.html @@ -188,7 +188,7 @@ construction of them that automatically handles many of the concerns outlined ab

TheoryΒΆ

A continuation is a suspended stack frame stored in a regular object that can be passed around, serialised, unserialised and resumed from where it was suspended. This may sound abstract but don’t worry, the examples below -will make it clearer. The JVM does not natively support continuations, so we implement them using a a library called +will make it clearer. The JVM does not natively support continuations, so we implement them using a library called JavaFlow which works through behind-the-scenes bytecode rewriting. You don’t have to know how this works to benefit from it, however.

We use continuations for the following reasons:

@@ -274,13 +274,13 @@ and returns it, with a StateMac

Note

-

Session IDs keep different traffic streams separated, so for security they must be large and random enough

+

Session IDs keep different traffic streams separated, so for security they must be large and random enough +to be unguessable. 63 bits is good enough.

-

to be unguessable. 63 bits is good enough.

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 .get() 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.

+to either runBuyer or runSeller, depending on who we are, and then call .resultFuture.get() on resulting object 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.

The only tricky part is how to get one of these things. We need a StateMachineManager. Where does that come from and why do we need one?

@@ -335,7 +335,8 @@ each side will use.

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.

-
// This object is serialised to the network and is the first protocol message the seller sends to the buyer.
+
// This object is serialised to the network and is the first protocol message
+// the seller sends to the buyer.
 class SellerTradeInfo(
       val assetForSale: StateAndRef<OwnableState>,
       val price: Amount,
@@ -355,13 +356,13 @@ trade’s messages, and a pointer to where the asset that is being sold can
 // Make the first message we'll send to kick off the protocol.
 val hello = SellerTradeInfo(args.assetToSell, args.price, args.myKeyPair.public, sessionID)
 
-// Zero is a special session ID that is being listened to by the buyer (i.e. before a session is started).
-val partialTX = sendAndReceive<SignedWireTransaction>(TRADE_TOPIC, args.buyerSessionID, sessionID, hello)
+val partialTX = sendAndReceive<SignedWireTransaction>(TRADE_TOPIC, args.buyerSessionID,
+        sessionID, hello)
 logger().trace { "Received partially signed transaction" }
 
-

That’s pretty straight forward. We generate a session ID to identify what’s happening on the seller side, fill out +

That’s pretty straightforward. We generate a session ID to identify what’s happening on the seller side, fill out the initial protocol message, and then call sendAndReceive. This function takes a few arguments:

  • A type argument, which is the object we’re expecting to receive from the other side.
  • @@ -453,16 +454,18 @@ forms.

    if (!args.typeToBuy.isInstance(tradeRequest.assetForSale.state)) throw AssetMismatchException(args.typeToBuy.name, assetTypeName) - // TODO: Either look up the stateref here in our local db, or accept a long chain of states and - // validate them to audit the other side and ensure it actually owns the state we are being offered! - // For now, just assume validity! + // TODO: Either look up the stateref here in our local db, or accept a long chain + // of states and validate them to audit the other side and ensure it actually owns + // the state we are being offered! For now, just assume validity! // Generate the shared transaction that both sides will sign, using the data we have. val ptx = PartialTransaction() - // Add input and output states for the movement of cash, by using the Cash contract to generate the states. + // Add input and output states for the movement of cash, by using the Cash contract + // to generate the states. val wallet = serviceHub.walletService.currentWallet val cashStates = wallet.statesOfType<Cash.State>() - val cashSigningPubKeys = Cash().craftSpend(ptx, tradeRequest.price, tradeRequest.sellerOwnerKey, cashStates) + val cashSigningPubKeys = Cash().craftSpend(ptx, tradeRequest.price, + tradeRequest.sellerOwnerKey, cashStates) // Add inputs/outputs/a command for the movement of the asset. ptx.addInputState(tradeRequest.assetForSale.ref) // Just pick some new public key for now. @@ -484,14 +487,17 @@ forms.

    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. + // 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) + val ltx = fullySigned.verifyToLedgerTransaction(serviceHub.timestampingService, + serviceHub.identityService) logger().trace { "Fully signed transaction was valid. Trade complete! :-)" } @@ -504,7 +510,8 @@ forms.

    This code is fairly straightforward. Here are some things to pay attention to:

    1. We do some sanity checking on the received message to ensure we’re being offered what we expected to be offered.
    2. -
    3. We create a cash spend in the normal way, by using Cash().craftSpend.
    4. +
    5. We create a cash spend in the normal way, by using Cash().craftSpend. See the contracts tutorial if this isn’t +clear.
    6. We access the service hub 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 @@ -520,7 +527,7 @@ the fact that it takes minimal resources and can survive node restarts.

      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 serviceHub field is defined by the ProtocolStateMachine 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 +this problem doesn’t occur. It’s also restored for you when a protocol state machine is restored after a node restart.

diff --git a/docs/build/html/searchindex.js b/docs/build/html/searchindex.js index 2e4562bc6a..39a15e9c7e 100644 --- a/docs/build/html/searchindex.js +++ b/docs/build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({envversion:46,filenames:["getting-set-up","index","inthebox","messaging","overview","protocol-state-machines","roadmap","tutorial","visualiser"],objects:{},objnames:{},objtypes:{},terms:{"0_xx":0,"1mb":5,"8u45":0,"abstract":5,"boolean":7,"break":7,"byte":[4,5],"case":[3,4,5,7],"catch":[0,5],"class":[1,3,5],"default":[0,7],"final":[3,5,6,7],"function":[1,3,4,5],"import":[0,3,4,7],"instanceof":7,"int":7,"long":[3,5,7],"new":[0,1,4,5,7],"null":7,"public":[2,3,4,5,6,7],"return":[3,5,7],"short":[3,7],"static":[5,7],"super":5,"switch":[5,7],"throw":[5,7],"transient":5,"true":[3,7,8],"try":[4,5,7,8],"var":7,"void":7,abil:[3,4,7],abl:3,abov:[3,5,7],accept:[3,4,5,7],acceptablepric:5,access:[3,5],accident:7,accord:5,account:4,achiev:3,across:5,act:3,action:7,actor:[5,7],actual:[3,5,7],adapt:6,add:[3,5,7],addarg:[5,7],addinputst:[5,7],addit:7,addition:5,addmessagehandl:3,addoutputst:[5,7],address:[3,4,7],administr:2,affection:7,after:[4,5,7,8],again:[3,7],against:[5,7],agre:[0,4,5],algorithm:[2,4,7,8],alic:[7,8],aliceaddr:3,alicegetsback:[7,8],alicenod:3,aliv:5,all:[0,3,4,5,6,7],allow:[4,5,6,7],allpossiblerecipi:3,almost:7,along:[3,4,5,7],alreadi:7,alright:5,also:[0,3,4,5,7],alt:7,alter:[5,7],although:[3,4,7],alwai:[4,7],amount:[2,5,6,7],ani:[3,4,5,7],annot:7,anoth:[5,7],anyon:7,anyth:[3,4,5,7],anywher:[3,7],apach:[3,6],api:[1,2,4,6],appear:[4,7],applic:4,approach:[4,5,6,7],arbitrari:[4,7],arbitrarili:4,area:3,aren:[5,7],arg:[5,7,8],argument:[3,4,5,7],around:[3,4,5,7,8],arrai:4,arrang:5,arriv:5,articl:[3,4,5],artifact:7,ask:7,assembl:4,assert:[5,7],asset:[1,4,5],assetforsal:5,assetmismatchexcept:5,assettosel:5,assettypenam:5,assist:[5,7,8],associ:[4,7],assum:[5,6,7],atom:[5,7],attach:[4,7],attempt:[0,1,3,4,5],attent:5,audit:[4,5,6],authenticatedobject:7,author:[3,4],authoris:5,auto:7,autom:7,automat:[3,5,7],avail:[3,7],avoid:5,awkward:5,back:[5,6,7],backend:[3,6],background:[3,4],backtick:7,bad:[5,7],balanc:7,bankrupt:7,base:[1,3,4,5,6],basic:[2,3,4,6,7],bear:[5,7],beauti:8,becaus:[0,3,5,7],becom:7,been:[4,7],befor:[4,5,7],begin:[4,5,7],behav:7,behaviour:2,behind:[5,7],below:5,benefit:[5,7],best:6,beta:0,better:[1,4,7,8],between:[5,7],beyond:[4,7],big:[5,7],bill:7,bind:4,bit:[5,7,8],bitbucket:0,bitcoinj:5,blank:7,block:[1,3,4,5,6,7],blockchain:5,blue:8,bob:7,bobaddr:3,bobnod:3,bond:7,bookkeep:[4,7],boost:2,borrow:8,both:[3,4,5,7],bound:5,briefli:8,bring:6,broadcast:3,brows:2,bug:2,build:[0,4,5,6,7],builder:7,built:[5,7],bunch:7,bundl:4,busi:[3,4,5,7],buyer:1,buyerimpl:5,buyerinitialarg:5,buyersessionid:5,bytearrai:3,bytecod:[4,5,7],calcul:[5,7],call:[3,4,5,7],callback:[3,5],caller:7,can:[0,2,3,4,5,6,7,8],cannot:[4,7],canon:6,capabl:[6,7],care:[3,5],carefulli:4,cash:[2,4,5,7,8],cashkt:7,cashsigningpubkei:5,cashstat:5,caus:7,center:7,certain:[4,7],cev:0,chain:[4,5,7],chanc:5,chang:[3,5,6,7,8],channel:5,chat:5,check:[0,1,2,5],checksufficientsignatur:5,choos:[0,7],circl:8,claim:[2,4,7],classload:5,clean:5,clearer:[3,5],click:[0,8],cluster:6,cmd:7,code:[0,2,3,4,5,6,7],codebas:7,collect:7,collector:5,com:[0,5],combin:[1,7],come:[4,5],command:[0,1,4,5],commerci:[1,2,4,5],commercial_pap:7,commercialpap:[4,7,8],commercialpapertest:[7,8],common:[5,7],commonli:7,commun:0,companion:[5,7],compar:[3,4],compil:7,complet:[3,4,5,7],complex:[4,5,7],complic:5,compos:[6,7],comput:5,concept:[4,7],conceptu:5,concern:[5,7],condit:5,confid:6,configur:0,conflict:[1,4,6],confus:5,connect:7,consensu:6,consid:[4,7],consist:[2,4,5],constant:7,construct:[3,5,7],constructor:7,consum:4,contact:5,contain:[4,5,6,7],content:[0,3,4,7],continu:5,contract:[1,2],contractst:[7,8],contractstateref:7,contrast:[4,5],contribut:7,control:[0,4,7],conveni:7,convert:7,convinc:5,copi:[5,7],core:[3,6,7],correct:7,correctli:[4,5,7],correspond:7,cost:7,could:[5,7],counter:5,coupl:5,cours:7,cover:[4,5,7],cp_program_id:7,craft:1,craftissu:7,craftmov:7,craftredeem:7,craftspend:[5,7],creat:[3,4,5,7],createmessag:3,creation:[1,7],crisp:7,crop:4,crowdfund:2,currenc:[4,7],current:[2,3,4,5,7,8],currentwallet:5,curv:2,dai:[7,8],dashboard:6,data:[1,2,3],databas:2,date:7,datetim:4,debug:5,decid:[4,7],declar:[3,5,7],defin:[2,3,4,5,7,8],definit:7,delet:7,deliv:3,deliveri:[3,5,7],demand:4,demonstr:6,denomin:4,depend:[0,5,7],deploy:6,deposit:4,depth:7,deriv:7,describ:[1,5,7],deseri:5,design:[1,4,7],desir:[5,7],despit:[5,7],destin:3,destroi:[4,7],destroypaperatredempt:[7,8],detail:[3,4,5,7],develop:[3,4,5],diagram:8,diamond:8,didn:7,differ:[4,5,7],difficult:[3,5],digit:[4,5,7],direct:7,directori:[0,7],dirti:7,disallow:7,discuss:3,disk:5,disprov:[1,6],disput:7,distinguish:7,distribut:[2,4,5,6],distrust:5,doc:7,document:[1,2,4,7],doe:[2,3,4,5,7],doesn:[3,4,5,7],dollar:[7,8],domain:[7,8],don:[0,3,4,5,7],done:[4,5,7],doubl:[5,6,7],doubt:4,down:7,download:[0,6],drag:8,drive:4,dsl:[6,7,8],due:[4,5,7],dummi:7,dummy_pubkey_1:7,duplic:7,durat:7,dynam:7,each:[3,4,5,7],earli:[7,8],eas:3,easi:7,easier:[5,7],easili:5,edit:0,editor:0,effect:7,either:[5,7],element:4,ellipt:2,els:7,emb:7,embed:4,emit:7,empti:[5,7],enabl:7,encapsul:5,encount:4,end:[4,5,7],enforc:[4,6,7],engin:7,english:7,enorm:5,enough:[3,5,6,7],ensur:[3,4,5,7],enter:7,entir:[3,4,7],entiti:[5,7],entri:[4,7],envisag:7,equal:7,equival:7,error:5,especi:8,essenti:7,etc:7,even:[3,4,5,6,7],event:6,everi:[4,5,7],everyth:[3,7],evolv:7,exact:7,exactli:[3,4,7],examin:[4,7],exampl:[3,5,6,7,8],except:7,exchang:[5,7],execut:[4,7],executor:3,exercis:7,exist:[1,4,7],expect:[2,3,5,7],expectfailureoftx:7,experi:6,experiment:[5,6],explain:[3,5,7],explicit:5,explicitli:[4,7],explor:[0,1,2,6,7],exploratori:3,expos:[3,4,5],express:[4,5,6,7],extend:[4,7],extens:7,extern:2,extract:[4,7],extrem:7,face:[4,7,8],facevalu:7,fact:[5,7],factor:4,fail:[3,7],failur:[5,7],fairli:5,fake:7,fals:[3,5,7],familiar:[4,7],far:[5,7],fast:3,favour:7,featur:[7,8],feel:7,few:[3,4,5,7],field:[5,7,8],file:[3,5,7],fill:[5,7],filterisinst:7,finalis:5,financ:5,financi:[1,4,5],find:[4,5],finish:[3,5],firm:7,first:[0,1,5,6,7],firstli:[5,7],fit:4,fix:[3,4,5,6],flesh:6,flexibl:4,flow:7,follow:[0,1,3,5,7,8],foo:3,fooutil:7,forget:7,form:[5,7],formal:7,format:4,forth:5,forward:5,found:[0,5],four:7,frame:5,framework:[2,4,5,8],free:[4,5,6],freeform:7,frequent:5,fresh:7,freshkei:5,freshli:7,from:[0,3,4,5,7,8],front:7,full:[5,7],fulli:[3,5,7],fullysign:5,fun:[5,7],fundament:[1,7],fungibl:[1,4],funni:5,futur:[1,4,5,6,7,8],gain:2,game:5,garbag:5,gather:7,gcd:4,gener:[5,7],getclass:7,getcommand:7,getfacevalu:7,getinput:7,getissu:7,getlegalcontractrefer:7,getmaturityd:7,getoutput:7,getown:7,getprogramref:7,getsign:7,getter:7,gettim:7,getvalu:7,git:0,give:[4,6,7],given:[3,4,7],global:[4,7],glue:5,goal:[1,2,4,5],gone:7,good:[5,6,7,8],got:5,gradl:[0,4],gradlew:0,graph:[4,7,8],green:0,group:[3,4,7,8],groupstat:7,guava:4,hack:4,had:7,hand:[5,7],handl:[3,4,5,6,7],handler:[3,5],happen:[5,7],happi:5,hard:5,hash:[2,4,7],hashcod:7,hassl:5,have:[3,4,5,6,7],haven:7,heap:5,heart:7,heavili:4,held:7,hell:5,hello:5,help:3,helper:[3,7],her:[7,8],here:[3,4,5,7,8],high:5,higher:[0,7],highlight:7,hit:0,hold:[3,4],holder:7,home:0,hotspot:6,how:[1,3,4,5,6],howev:[5,7],http:[0,7],hub:5,hundr:5,hypothesi:1,idea:[0,2,4,5,7],ideal:[5,7],ident:[4,5,7],identifi:[3,4,5],identityservic:5,ietf:4,ignor:7,illegalargumentexcept:7,illegalstateexcept:7,imagin:[5,7],immedi:7,immut:[4,7],impl:5,implement:[1,2],impli:5,implicitli:7,impos:[5,7],improv:[4,6,7,8],inbackground:3,includ:1,incorrect:5,increas:3,independ:7,index:[4,7],indic:[5,7],individu:[3,7],industri:[1,4],infer:7,infix:7,info:5,inform:[4,7],inherit:[3,5,7],initi:[3,5,7],inmemorymessagingtest:3,inoutgroup:7,input:[4,5,7,8],insert:3,insid:[3,4,5,7],instal:0,instanc:[4,5,7],instant:7,instanti:[4,5],instead:[2,4,7],institut:4,institutionrefer:7,instruct:7,insufficientbalanceexcept:7,integ:7,integr:[2,8],intend:[4,5],intent:[7,8],interact:[4,5],interest:[5,7,8],interfac:[1,2],interfer:5,intern:[4,6,7],internet:4,interop:[4,7],interpret:[4,7],intersect:7,introduc:[6,7],introduct:[1,4],invalid:[5,7],invari:7,invoc:3,invok:[3,4,5,7],involv:[3,5,7],isaft:7,isempti:7,isinst:5,isn:[5,7],issu:[4,6,7,8],issuanc:[7,8],issuer:7,item:[0,7],iter:[5,7],itself:[3,4,7],java:[3,4,5,7],javaclass:5,javacommercialpap:7,javaflow:5,jdk1:0,jdk:[0,7],jetbrain:[0,4],jira:[2,6],jmx:6,join:7,joint:7,junit:[4,7],just:[0,3,4,5,7],justifi:1,jvm:[4,5,6],jvmstatic:5,kafka:[3,6],keep:[4,5,7,8],kei:[2,3,4,5,6,7],kept:5,key_mismatch_at_issu:7,keymanagementservic:5,keypair:[5,7],keyword:7,kick:5,kill:6,kind:[3,4,7],know:[4,5],known:4,kotin:7,kotlin:[0,1,3],kryo:[3,4,5],label:[7,8],labori:7,languag:[0,1,4,7,8],larg:5,later:[2,3,5,6,7],latest:0,latter:7,layer:[5,6],layout:8,lazi:6,lazili:7,lead:7,learn:[1,6],least:7,leav:5,ledger:[1,4,5,7,8],ledgertransact:5,left:[3,5],legal:7,legalcontractrefer:7,less:[5,7,8],let:[4,5,7],level:[0,3,7],librari:[4,5,7],lifecycl:[5,7,8],like:[0,3,4,5,6,7],likewis:7,limit:[1,4,6,7],line:[0,5,7],link:7,list:[3,7],listen:5,liter:4,littl:7,load:7,local:[0,4,5],locat:7,lock:7,log:[5,6],logger:5,logic:[3,4,5,6,7],logo:0,look:[5,7],loop:7,lose:6,low:5,ltx:5,lurch:5,machin:[1,3,4],made:1,mai:[3,4,5,6,7],main:[5,7,8],maintain:4,make:[3,5,6,7],makenod:3,maker:4,malici:5,manag:1,mani:[2,3,4,5,7],manual:3,map:7,mappabl:7,mark:[5,7],marker:7,market:1,match:[3,4,7],matur:7,maturityd:7,maximis:4,mean:[3,4],measur:[6,7],mechan:7,meet:7,mega_corp:7,mega_corp_kei:7,mega_corp_pubkei:8,megacorp:[7,8],member:5,memori:1,menu:0,mere:[4,7],merg:[4,7],mess:5,messag:1,messagehandlerregistr:3,messagerecipi:3,messagerecipientgroup:3,messagingservic:[3,5],method:[3,5,7,8],middl:[3,5],might:[5,7],mileston:6,mind:[5,7],mine:4,minim:5,minimum:[4,6],minu:7,minut:4,misc:3,miss:[5,7],mix:[5,6,7],mock:[3,6],mode:3,model:1,modif:[6,7],modifi:[0,7],modul:[3,7],moment:3,monei:7,monetari:7,monitor:6,month:5,more:[3,4,7],most:[3,5,7],mostli:7,move:[5,7,8],movement:[5,7],much:[4,5,7],multi:[5,6,7],multipl:[3,4,7],must:[4,5,7],mutabl:[4,7],mutual:5,mykeypair:5,name:[3,4,5,7],nativ:5,natur:7,necessari:6,necessarili:[6,7],need:[1,3,4,5,7],neither:[5,7],nest:5,net:[7,8],network:[1,2],neutral:2,never:[4,7],newown:7,next:[0,5,6,7],node:[3,4,5,6,8],non:[1,4],normal:[5,7],not_matured_at_redempt:7,note:[0,4,5,7],noth:[4,7],notic:7,notion:[2,4,7],notnul:7,now:[0,3,4,5,7,8],nugget:7,nullpublickei:7,number:7,obj:7,object:[3,4,5,7,8],observ:6,obsolet:2,obtain:8,obvious:7,occur:[5,7],odd:[5,7],off:[3,5,7,8],offer:5,often:[4,5,7],onc:[3,4,5,7],onli:[3,4,5,7,8],onto:[7,8],opaqu:[3,4],opaquebyt:7,open:[0,5,8],openjdk:0,oper:[3,7],opposit:7,option:[3,7],oracl:0,order:[2,4,7,8],ordinari:[4,5,7],org:[0,7],orient:1,origin:7,other:[2,3,4,5,6,7],othersid:5,otherwis:7,our:[4,5,6,7],ourselv:[5,7],oursignatur:5,out:[0,4,5,6,7],outcom:5,outlin:5,outpoint:4,output:[4,5,7,8],outputst:5,outsid:[3,5,7],outstat:7,over:[3,5,7],overrid:[5,7],overview:1,own:[3,4,5,7,8],ownablest:5,owned_bi:7,owner:[5,6,7],ownership:[5,7],owningkei:7,p2p:6,packag:6,packet:4,page:[6,7],pai:[5,7,8],pair:[4,5],paper:[1,2,4,5],paper_1:[7,8],parallel:[3,7],paramet:[5,7],parameteris:4,part:[4,5,6,7],parti:[1,4],partial:[5,7],partialtransact:[5,7],partialtx:5,particip:[4,7],particular:5,partner:5,pass:[3,5,7,8],past:7,path:7,pattern:[4,7],payment:[5,7,8],peer:[2,3],pend:6,penni:7,peopl:[4,7],perform:[5,7],perhap:7,perman:[4,7],persist:[2,3,5],perspect:[5,7],pick:5,piec:[3,4,5,7],ping:3,place:[2,4,6,7],plai:5,platform:[1,3,4,5,7],playground:0,pleas:[4,7],pluggabl:6,plugin:0,point:[4,5,7],pointer:[4,5],pong:3,pool:[5,6],poor:4,pop:[0,3],popular:4,posess:5,possibl:[1,3,4,5,7],potenti:[4,7],pound:7,power:[1,4],practic:[4,7],pre:[5,7],preced:7,preliminari:3,prepar:7,presenc:6,present:[1,6,7],press:7,pretti:[5,7],prevent:7,price:5,primari:4,primit:7,priv:5,privaci:7,privat:[4,5,7],probabl:[0,7],problem:[5,7],proce:5,process:[3,7],produc:[5,7,8],product:[1,2,7],profit:[7,8],program:[3,4,7],programref:7,progress:5,project:0,proof:[1,4],propag:[1,7],properti:7,protect:5,protocol:[1,2,3,4],protocolstatemachin:5,prove:[1,4,6,7],provid:[3,4,5,7],ptx:5,publickei:[5,7],pull:0,pump:3,purchas:5,pure:4,purpos:[4,7],put:[5,7],qualiti:1,quantiti:[4,7],queue:3,quickli:[3,7],quit:[5,7],r3cev:5,random63bitvalu:5,random:[4,5],rapid:2,rather:[4,5,7],rational:4,reachabl:5,read:[1,2,4,5,7],readabl:4,reader:7,readi:7,real:[2,3,7],realism:3,realiti:7,realli:[5,7],reason:[5,7],reassign:7,receiv:[3,4,5,7,8],recipi:[3,7],recognis:7,record:[6,7],recreat:5,red:0,redeem:[4,7,8],redempt:[7,8],redemptiontim:[7,8],ref:[5,7],refer:[4,5,7],refin:4,reflect:7,refus:0,regist:[3,5],registr:3,registri:4,regular:[4,5,7],reissuanc:7,reject:7,rel:4,relat:[5,7],relationship:7,releas:8,relev:4,reli:4,reliabl:3,relianc:4,remain:[7,8],rememb:[5,7],remov:[3,7],render:8,repeat:3,replac:7,replic:4,report:[3,6],repres:[3,4,5,7],request:5,requir:[1,3,4,5,6],requiresinglecommand:7,requirethat:[5,7],resolut:[1,4,6],resolv:[5,6],resourc:5,respect:7,respons:5,rest:[3,4],restart:[0,5],restor:5,result:[4,5,7],resum:5,resurrect:5,retri:3,reus:5,reveal:7,rewrit:5,rfc:4,right:[0,3,5],rigid:4,risk:5,roadmap:1,roll:6,rollov:7,room:5,root:[7,8],rout:[5,6],router:3,rule:[5,7],run:[0,3,4,5,7],runawai:6,runbuy:5,runnetwork:3,runsel:5,runtim:6,safe:[4,5,6,7],sai:[4,7],sale:7,same:[3,4,5,7,8],sandbox:[2,4,6,7],saniti:5,satisfi:[5,7],save:7,scala:[4,7],scalabl:[4,7],scene:[5,7],scope:[4,7],screen:0,script:[4,7],seamless:4,search:[0,7],second:[5,7],secondari:5,secp256r1:2,section:7,secur:[3,4,5],securehash:7,see:[3,5,6,7],seen:[6,7,8],select:[0,7],sell:[5,7],seller:1,sellerimpl:5,sellerinitialarg:5,sellerownerkei:5,sellertradeinfo:5,semi:4,send:[3,4,5,7],sendandrec:5,sens:[5,7],sent:[3,5,7],separ:[5,6,7],sequenc:3,sequenti:5,serial:[2,7],serialis:[2,3,4,5,7],serializablewithkryo:7,serializeablewithkryo:7,server:6,servic:[3,5],servicehub:5,session:[3,5],sessionid:5,setter:7,settl:3,settlement:5,sever:[4,5,7],sha256:7,sha:4,share:[1,4,5,7],she:7,shortcut:2,shorthand:7,shot:3,should:[0,2,3,4,5,6,7],shouldn:5,show:[0,4,7,8],shown:7,shutdown:5,side:5,sig:[5,7],sign:[2,4,5,7],signatur:[2,4,5,6,7],signedwiretransact:[5,7],signer:7,signwith:[5,7],signwithecdsa:5,similar:[4,7],similarli:7,simpl:[3,5,7,8],simpler:4,simplest:5,simpli:[3,5,7],simplifi:[2,3,4,7],simultan:[3,5,7],singl:[4,5,7,8],singlemessagerecipi:[3,5],singleton:7,sit:3,site:6,size:[5,7],skeleton:5,slight:7,slightli:7,small:[2,4,5,7,8],smart:[1,2],smm:5,smooth:7,snippet:7,softwar:2,sold:[5,7,8],solv:[5,7],some:[2,3,4,5,6,7,8],somed:7,someon:[3,7],someprofit:[7,8],someth:[0,5,7],sometim:[3,4,7],somewhat:4,somewher:[7,8],sort:[4,5],sound:[5,7,8],sourc:5,space:7,special:5,specif:[3,4,5,7,8],specifi:[2,3,7],speed:5,spend:[4,5,6,7],split:[4,7],spread:[3,5],squar:8,src:[7,8],stack:5,stage:[5,6,7],stai:4,standard:[1,4,7],standardis:[4,7],start:[1,5],state:[1,3,4],stateandref:[5,7],stateless:4,statemachinemanag:5,statement:[5,7],stateref:[4,5],statesoftyp:5,step:[5,6,7],still:[4,7],stop:[3,5,6],storag:[4,6],store:[5,7],straight:5,straightforward:[5,7],stream:5,string:[3,5,7],strong:4,structur:[0,2,4,5,7],studi:7,stuff:5,stx:5,style:3,subgraph:6,subgroup:4,submenu:0,successor:4,suffici:[1,3],suffix:7,suggest:7,suitabl:6,sum:7,sumcashbi:[5,7],sumcashornul:7,summaris:4,superclass:5,supertyp:7,support:[4,5,6,7],suppos:[5,7],sure:[5,7],surround:7,surviv:5,suspend:5,swap:5,symbol:0,synchronis:4,syntax:[4,7],system:[2,4,5,6,7],tab:0,tailor:1,take:[2,5,7,8],target:4,targetrecipi:3,task:[4,5,6],techniqu:7,tell:3,tempor:6,temporarili:5,tempt:7,temptat:5,ten:7,term:[4,7],termin:5,terminolog:4,test:[0,1,2,3,4,5,6],test_tx_tim:7,testutil:7,testwithinmemorynetwork:3,text:0,than:[1,4,5,7,8],thei:[3,4,5,6,7],them:[2,3,5,7],themselv:[3,4,7],theori:1,therefor:[2,4,7],thesi:6,thi:[0,1,3,4,5,6,7,8],thing:[2,4,5,6,7],think:[0,5,7],third:[5,7],those:[3,7],though:[3,5,7],thought:4,thread:[3,5,6],three:[2,7],threshold:7,through:[4,5,6,7],thrown:7,thu:7,tighten:7,tightli:5,time:[4,5,6,7,8],timelin:7,timestamp:[4,5,7],timestampedwiretransact:5,timestampingservic:5,todo:[5,7],togeth:[4,7],too:[5,7,8],took:5,tool:4,top:[5,7],topic:[3,5],topriv:5,tosignedtransact:[5,7],tostr:7,total:7,totimestampedtransact:5,trace:5,track:5,tracker:2,trade:[1,4],trade_top:5,traderequest:5,tradit:7,traffic:5,transact:[1,4,5,6,7,8],transactionforverif:7,transactiongroup:[5,7],transactiongroupdsl:8,transactiongroupfor:8,transactiongroupfortest:7,transfer:7,transit:[1,7],treat:7,tri:7,trick:5,tricki:5,tripl:4,truth:5,tsa:4,tsp:4,ture:4,turn:[5,7],tutori:[1,2,4],twice:4,two:[1,3,4],twopartytradeprotocol:5,twopartytradeprotocolimpl:5,txbit:5,txhash:[4,7],type:[4,5,7],typetobui:5,typic:[3,5,7],unacceptablepriceexcept:5,under:7,underscor:7,understand:[1,3],unexecut:7,unfinsish:5,unfortun:[5,7],unguess:5,uniqu:4,unit:[0,2,3,4,5,7,8],unless:[5,7],unlik:7,unnecessari:7,unpack:5,unread:5,unrecognis:7,unsaf:6,unserialis:5,unspent:4,unsupportedoperationexcept:7,until:[3,5],unus:3,unusu:7,unwieldi:7,updat:[0,4,5,7],upgrad:[0,1,6],upload:6,upon:[4,7],url:0,usabl:4,usag:7,user:[2,3,4,5],util:[3,4,7],utxo:4,val:[3,5,7,8],valid:[4,5,6,7],valu:[4,7,8],vari:7,variabl:[5,7],variant:7,variou:[4,5,7],vendor:2,verbos:7,veri:[4,8],verif:[2,4],verifi:[1,2,4,5,6],verifysignatur:5,verifytoledgertransact:5,versa:5,version:[0,2,5,7],versu:5,via:5,vice:5,virtual:[1,4],visibl:4,visualis:1,vote:6,wai:[4,5,6,7],wait:[0,3,5],wallet:[4,5,7],walletservic:5,wan:6,want:[0,3,5,7],websit:7,well:[2,4,5,7],were:[5,7],what:1,whatev:5,when:[3,5,6,7],where:[3,4,5],wherea:7,whether:3,which:[2,3,4,5,7],whilst:[4,5,7],who:[3,4,5,7],whole:7,why:[4,5,7],wide:[3,7],wiki:[4,7],wikipedia:7,window:8,wire:5,wirecommand:[5,7],wiretransact:5,wish:[3,5,6,7],within:4,withnewown:5,withoutown:7,won:[3,7],work:[0,1,2,3,4,5,7],world:[5,7],worn:7,worri:[4,5],worth:7,would:[2,3,5,7],wouldn:7,wrap:7,wrapper:5,write:[4,5,7],written:[4,7],wtx:5,www:0,yet:[4,7],yield:4,you:[0,2,3,4,5,7,8],your:[1,3,5],your_usernam:0,zero:[5,7]},titles:["Getting set up","Welcome to the R3 prototyping repository!","What’s included?","Networking and messaging","Overview","Protocol state machines","Roadmap","Tutorial","Using the visualiser"],titleterms:{"class":7,"function":7,about:0,api:7,asset:7,base:7,bitcoin:4,buyer:5,check:7,command:7,commerci:7,comparison:4,complain:0,contract:[4,7],craft:7,data:4,ethereum:4,fungibl:7,get:0,how:7,implement:[3,5],includ:2,intellij:0,interfac:3,introduct:5,kotlin:4,lack:0,machin:5,manag:5,memori:3,messag:3,model:4,network:3,non:7,orient:7,overview:4,paper:7,parti:5,protocol:5,prototyp:1,repositori:1,requir:7,roadmap:6,sdk:0,seller:5,set:0,smart:7,start:7,state:[5,7],test:7,theori:5,trade:5,tutori:7,two:5,understand:7,verifi:7,visualis:8,welcom:1,what:2,without:0,your:7}}) \ No newline at end of file +Search.setIndex({envversion:46,filenames:["getting-set-up","index","inthebox","messaging","overview","protocol-state-machines","roadmap","tutorial","visualiser"],objects:{},objnames:{},objtypes:{},terms:{"0_xx":0,"1mb":5,"8u45":0,"abstract":5,"boolean":7,"break":7,"byte":[4,5],"case":[3,4,5,7],"catch":[0,5],"class":3,"default":[0,7],"final":[3,5,6,7],"function":[3,4],"import":[0,3,4,7],"instanceof":7,"int":7,"long":[3,5,7],"new":[0,1,4,5,7],"null":7,"public":[2,3,4,5,6,7],"return":[3,5,7],"short":[3,7],"static":[5,7],"super":5,"switch":[5,7],"throw":[5,7],"transient":5,"true":[3,7,8],"try":[4,5,7,8],"var":7,"void":7,abil:[3,4,7],abl:3,abov:[3,5,7],accept:[3,4,5,7],acceptablepric:5,access:[3,5],accident:7,accord:5,account:4,achiev:3,across:5,act:3,action:7,actor:[5,7],actual:[3,5,7],adapt:6,add:[3,5,7],addarg:[5,7],addinputst:[5,7],addit:7,addition:5,addmessagehandl:3,addoutputst:[5,7],address:[3,4,7],administr:2,affection:7,after:[4,5,7,8],again:[3,7],against:[5,7],agre:[0,4,5],algorithm:[2,4,7,8],alic:[7,8],aliceaddr:3,alicegetsback:[7,8],alicenod:3,aliv:5,all:[0,3,4,5,6,7],allow:[4,5,6,7],allpossiblerecipi:3,almost:7,along:[3,4,5,7],alreadi:7,alright:5,also:[0,3,4,5,7],alt:7,alter:[5,7],although:[3,4,7],alwai:[4,7],amount:[2,5,6,7],ani:[3,4,5,7],annot:7,anoth:[5,7],anyon:7,anyth:[3,4,5,7],anywher:[3,7],apach:[3,6],api:[2,4,6],appear:[4,7],applic:4,approach:[4,5,6,7],arbitrari:[4,7],arbitrarili:4,area:3,aren:[5,7],arg:[5,7,8],argument:[3,4,5,7],around:[3,4,5,7,8],arrai:4,arrang:5,arriv:5,articl:[3,4,5],artifact:7,ask:7,assembl:4,assert:[5,7],asset:4,assetforsal:5,assetmismatchexcept:5,assettosel:5,assettypenam:5,assist:[5,7,8],associ:[4,7],assum:[5,6,7],atom:[5,7],attach:[4,7],attempt:[0,1,3,4,5],attent:5,audit:[4,5,6],authenticatedobject:7,author:[3,4],authoris:5,auto:7,autom:7,automat:[3,5,7],avail:[3,7],avoid:5,awkward:5,back:[5,6,7],backend:[3,6],background:[3,4],backtick:7,bad:[5,7],balanc:7,bankrupt:7,base:[3,4,6],basic:[2,3,4,6,7],bear:[5,7],beauti:8,becaus:[0,3,5,7],becom:7,been:[4,7],befor:[4,5,7],begin:[4,5,7],behav:7,behaviour:2,behind:[5,7],below:5,benefit:[5,7],best:6,beta:0,better:[1,4,7,8],between:[5,7],beyond:[4,7],big:[5,7],bill:7,bind:4,bit:[5,7,8],bitbucket:0,bitcoinj:5,blank:7,block:[1,3,4,5,6,7],blockchain:5,blue:8,bob:7,bobaddr:3,bobnod:3,bond:7,bookkeep:[4,7],boost:2,borrow:8,both:[3,4,5,7],bound:5,briefli:8,bring:6,broadcast:3,brows:2,bug:2,build:[0,4,5,6,7],builder:7,built:[5,7],bunch:7,bundl:4,busi:[3,4,5,7],buyer:[],buyerimpl:5,buyerinitialarg:5,buyersessionid:5,bytearrai:3,bytecod:[4,5,7],calcul:[5,7],call:[3,4,5,7],callback:[3,5],caller:7,can:[0,2,3,4,5,6,7,8],cannot:[4,7],canon:6,capabl:[6,7],care:[3,5],carefulli:4,cash:[2,4,5,7,8],cashkt:7,cashsigningpubkei:5,cashstat:5,caus:7,center:7,certain:[4,7],cev:0,chain:[4,5,7],chanc:5,chang:[3,5,6,7,8],channel:5,chat:5,check:[0,2],checksufficientsignatur:5,choos:[0,7],circl:8,claim:[2,4,7],classload:5,clean:5,clear:5,clearer:[3,5],click:[0,8],cluster:6,cmd:7,code:[0,2,3,4,5,6,7],codebas:7,collect:7,collector:5,com:[0,5],combin:[1,7],come:[4,5],command:[0,4],commerci:[2,4],commercial_pap:7,commercialpap:[4,7,8],commercialpapertest:[7,8],common:[5,7],commonli:7,commun:0,companion:[5,7],compar:[3,4],compil:7,complet:[3,4,5,7],complex:[4,5,7],complic:5,compos:[6,7],comput:5,concept:[4,7],conceptu:5,concern:[5,7],condit:5,confid:6,configur:0,conflict:[1,4,6],confus:5,connect:7,consensu:6,consid:[4,7],consist:[2,4,5],constant:7,construct:[3,5,7],constructor:7,consum:4,contact:5,contain:[4,5,6,7],content:[0,3,4,7],continu:5,contract:2,contractst:[7,8],contractstateref:7,contrast:[4,5],contribut:7,control:[0,4,7],conveni:7,convert:7,convinc:5,copi:[5,7],core:[3,6,7],correct:7,correctli:[4,5,7],correspond:7,cost:7,could:[5,7],counter:5,coupl:5,cours:7,cover:[4,5,7],cp_program_id:7,craft:[],craftissu:7,craftmov:7,craftredeem:7,craftspend:[5,7],creat:[3,4,5,7],createmessag:3,creation:[1,7],crisp:7,crop:4,crowdfund:2,currenc:[4,7],current:[2,3,4,5,7,8],currentwallet:5,curv:2,dai:[7,8],dashboard:6,data:[2,3],databas:2,date:7,datetim:4,debug:5,decid:[4,7],declar:[3,5,7],defin:[2,3,4,5,7,8],definit:7,delet:7,deliv:3,deliveri:[3,5,7],demand:4,demonstr:6,denomin:4,depend:[0,5,7],deploy:6,deposit:4,depth:7,deriv:7,describ:[1,5,7],deseri:5,design:[1,4,7],desir:[5,7],despit:[5,7],destin:3,destroi:[4,7],destroypaperatredempt:[7,8],detail:[3,4,5,7],develop:[3,4,5],diagram:8,diamond:8,didn:7,differ:[4,5,7],difficult:[3,5],digit:[4,5,7],direct:7,directori:[0,7],dirti:7,disallow:7,discuss:3,disk:5,disprov:[1,6],disput:7,distinguish:7,distribut:[2,4,5,6],distrust:5,doc:7,document:[1,2,4,7],doe:[2,3,4,5,7],doesn:[3,4,5,7],dollar:[7,8],domain:[7,8],don:[0,3,4,5,7],done:[4,5,7],doubl:[5,6,7],doubt:4,down:7,download:[0,6],drag:8,drive:4,dsl:[6,7,8],due:[4,5,7],dummi:7,dummy_pubkey_1:7,duplic:7,durat:7,dynam:7,each:[3,4,5,7],earli:[7,8],eas:3,easi:7,easier:[5,7],easili:5,edit:0,editor:0,effect:7,either:[5,7],element:4,ellipt:2,els:7,emb:7,embed:4,emit:7,empti:[5,7],enabl:7,encapsul:5,encount:4,end:[4,5,7],enforc:[4,6,7],engin:7,english:7,enorm:5,enough:[3,5,6,7],ensur:[3,4,5,7],enter:7,entir:[3,4,7],entiti:[5,7],entri:[4,7],envisag:7,equal:7,equival:7,error:5,especi:8,essenti:7,etc:7,even:[3,4,5,6,7],event:6,everi:[4,5,7],everyth:[3,7],evolv:7,exact:7,exactli:[3,4,7],examin:[4,7],exampl:[3,5,6,7,8],except:7,exchang:[5,7],execut:[4,7],executor:3,exercis:7,exist:[1,4,7],expect:[2,3,5,7],expectfailureoftx:7,experi:6,experiment:[5,6],explain:[3,5,7],explicit:5,explicitli:[4,7],explor:[0,1,2,6,7],exploratori:3,expos:[3,4,5],express:[4,5,6,7],extend:[4,7],extens:7,extern:2,extract:[4,7],extrem:7,face:[4,7,8],facevalu:7,fact:[5,7],factor:4,fail:[3,7],failur:[5,7],fairli:5,fake:7,fals:[3,5,7],familiar:[4,7],far:[5,7],fast:3,favour:7,featur:[7,8],feel:7,few:[3,4,5,7],field:[5,7,8],file:[3,5,7],fill:[5,7],filterisinst:7,finalis:5,financ:5,financi:[1,4,5],find:[4,5],finish:[3,5],firm:7,first:[0,1,5,6,7],firstli:[5,7],fit:4,fix:[3,4,5,6],flesh:6,flexibl:4,flow:7,follow:[0,1,3,5,7,8],foo:3,fooutil:7,forget:7,form:[5,7],formal:7,format:4,forth:5,forward:[],found:[0,5],four:7,frame:5,framework:[2,4,5,8],free:[4,5,6],freeform:7,frequent:5,fresh:7,freshkei:5,freshli:7,from:[0,3,4,5,7,8],front:7,full:[5,7],fulli:[3,5,7],fullysign:5,fun:[5,7],fundament:[1,7],fungibl:4,funni:5,futur:[1,4,5,6,7,8],gain:2,game:5,garbag:5,gather:7,gcd:4,gener:[5,7],getclass:7,getcommand:7,getfacevalu:7,getinput:7,getissu:7,getlegalcontractrefer:7,getmaturityd:7,getoutput:7,getown:7,getprogramref:7,getsign:7,getter:7,gettim:7,getvalu:7,git:0,give:[4,6,7],given:[3,4,7],global:[4,7],glue:5,goal:[1,2,4,5],gone:7,good:[5,6,7,8],got:5,gradl:[0,4],gradlew:0,graph:[4,7,8],green:0,group:[3,4,7,8],groupstat:7,guava:4,hack:4,had:7,hand:[5,7],handl:[3,4,5,6,7],handler:[3,5],happen:[5,7],happi:5,hard:5,hash:[2,4,7],hashcod:7,hassl:5,have:[3,4,5,6,7],haven:7,heap:5,heart:7,heavili:4,held:7,hell:5,hello:5,help:3,helper:[3,7],her:[7,8],here:[3,4,5,7,8],high:5,higher:[0,7],highlight:7,hit:0,hold:[3,4],holder:7,home:0,hotspot:6,how:[3,4,6],howev:[5,7],http:[0,7],hub:5,hundr:5,hypothesi:1,idea:[0,2,4,5,7],ideal:[5,7],ident:[4,5,7],identifi:[3,4,5],identityservic:5,ietf:4,ignor:7,illegalargumentexcept:7,illegalstateexcept:7,imagin:[5,7],immedi:7,immut:[4,7],impl:5,implement:2,impli:5,implicitli:7,impos:[5,7],improv:[4,6,7,8],inbackground:3,includ:[],incorrect:5,increas:3,independ:7,index:[4,7],indic:[5,7],individu:[3,7],industri:[1,4],infer:7,infix:7,info:5,inform:[4,7],inherit:[3,5,7],initi:[3,5,7],inmemorymessagingtest:3,inoutgroup:7,input:[4,5,7,8],insert:3,insid:[3,4,5,7],instal:0,instanc:[4,5,7],instant:7,instanti:[4,5],instead:[2,4,7],institut:4,institutionrefer:7,instruct:7,insufficientbalanceexcept:7,integ:7,integr:[2,8],intend:[4,5],intent:[7,8],interact:[4,5],interest:[5,7,8],interfac:2,interfer:5,intern:[4,6,7],internet:4,interop:[4,7],interpret:[4,7],intersect:7,introduc:[6,7],introduct:4,invalid:[5,7],invari:7,invoc:3,invok:[3,4,5,7],involv:[3,5,7],isaft:7,isempti:7,isinst:5,isn:[5,7],issu:[4,6,7,8],issuanc:[7,8],issuer:7,item:[0,7],iter:[5,7],itself:[3,4,7],java:[3,4,5,7],javaclass:5,javacommercialpap:7,javaflow:5,jdk1:0,jdk:[0,7],jetbrain:[0,4],jira:[2,6],jmx:6,join:7,joint:7,junit:[4,7],just:[0,3,4,5,7],justifi:1,jvm:[4,5,6],jvmstatic:5,kafka:[3,6],keep:[4,5,7,8],kei:[2,3,4,5,6,7],kept:5,key_mismatch_at_issu:7,keymanagementservic:5,keypair:[5,7],keyword:7,kick:5,kill:6,kind:[3,4,7],know:[4,5],known:4,kotin:7,kotlin:[0,3],kryo:[3,4,5],label:[7,8],labori:7,languag:[0,1,4,7,8],larg:5,later:[2,3,5,6,7],latest:0,latter:7,layer:[5,6],layout:8,lazi:6,lazili:7,lead:7,learn:[1,6],least:7,leav:5,ledger:[1,4,5,7,8],ledgertransact:5,left:[3,5],legal:7,legalcontractrefer:7,less:[5,7,8],let:[4,5,7],level:[0,3,7],librari:[4,5,7],lifecycl:[5,7,8],like:[0,3,4,5,6,7],likewis:7,limit:[1,4,6,7],line:[0,5,7],link:7,list:[3,7],listen:[],liter:4,littl:7,load:7,local:[0,4,5],locat:7,lock:7,log:[5,6],logger:5,logic:[3,4,5,6,7],logo:0,look:[5,7],loop:7,lose:6,low:5,ltx:5,lurch:5,machin:[3,4],made:1,mai:[3,4,5,6,7],main:[5,7,8],maintain:4,make:[3,5,6,7],makenod:3,maker:4,malici:5,manag:[],mani:[2,3,4,5,7],manual:3,map:7,mappabl:7,mark:[5,7],marker:7,market:1,match:[3,4,7],matur:7,maturityd:7,maximis:4,mean:[3,4],measur:[6,7],mechan:7,meet:7,mega_corp:7,mega_corp_kei:7,mega_corp_pubkei:8,megacorp:[7,8],member:5,memori:[],menu:0,mere:[4,7],merg:[4,7],mess:5,messag:[],messagehandlerregistr:3,messagerecipi:3,messagerecipientgroup:3,messagingservic:[3,5],method:[3,5,7,8],middl:[3,5],might:[5,7],mileston:6,mind:[5,7],mine:4,minim:5,minimum:[4,6],minu:7,minut:4,misc:3,miss:[5,7],mix:[5,6,7],mock:[3,6],mode:3,model:[],modif:[6,7],modifi:[0,7],modul:[3,7],moment:3,monei:7,monetari:7,monitor:6,month:5,more:[3,4,7],most:[3,5,7],mostli:7,move:[5,7,8],movement:[5,7],much:[4,5,7],multi:[5,6,7],multipl:[3,4,7],must:[4,5,7],mutabl:[4,7],mutual:5,mykeypair:5,name:[3,4,5,7],nativ:5,natur:7,necessari:6,necessarili:[6,7],need:[1,3,4,5,7],neither:[5,7],nest:5,net:[7,8],network:2,neutral:2,never:[4,7],newown:7,next:[0,5,6,7],node:[3,4,5,6,8],non:4,normal:[5,7],not_matured_at_redempt:7,note:[0,4,5,7],noth:[4,7],notic:7,notion:[2,4,7],notnul:7,now:[0,3,4,5,7,8],nugget:7,nullpublickei:7,number:7,obj:7,object:[3,4,5,7,8],observ:6,obsolet:2,obtain:8,obvious:7,occur:[5,7],odd:[5,7],off:[3,5,7,8],offer:5,often:[4,5,7],onc:[3,4,5,7],onli:[3,4,5,7,8],onto:[7,8],opaqu:[3,4],opaquebyt:7,open:[0,5,8],openjdk:0,oper:[3,7],opposit:7,option:[3,7],oracl:0,order:[2,4,7,8],ordinari:[4,5,7],org:[0,7],orient:[],origin:7,other:[2,3,4,5,6,7],othersid:5,otherwis:7,our:[4,5,6,7],ourselv:[5,7],oursignatur:5,out:[0,4,5,6,7],outcom:5,outlin:5,outpoint:4,output:[4,5,7,8],outputst:5,outsid:[3,5,7],outstat:7,over:[3,5,7],overrid:[5,7],overview:[],own:[3,4,5,7,8],ownablest:5,owned_bi:7,owner:[5,6,7],ownership:[5,7],owningkei:7,p2p:6,packag:6,packet:4,page:[6,7],pai:[5,7,8],pair:[4,5],paper:[2,4],paper_1:[7,8],parallel:[3,7],paramet:[5,7],parameteris:4,part:[4,5,6,7],parti:4,partial:[5,7],partialtransact:[5,7],partialtx:5,particip:[4,7],particular:5,partner:5,pass:[3,5,7,8],past:7,path:7,pattern:[4,7],payment:[5,7,8],peer:[2,3],pend:6,penni:7,peopl:[4,7],perform:[5,7],perhap:7,perman:[4,7],persist:[2,3,5],perspect:[5,7],pick:5,piec:[3,4,5,7],ping:3,place:[2,4,6,7],plai:5,platform:[1,3,4,5,7],playground:0,pleas:[4,7],pluggabl:6,plugin:0,point:[4,5,7],pointer:[4,5],pong:3,pool:[5,6],poor:4,pop:[0,3],popular:4,posess:5,possibl:[1,3,4,5,7],potenti:[4,7],pound:7,power:[1,4],practic:[4,7],pre:[5,7],preced:7,preliminari:3,prepar:7,presenc:6,present:[1,6,7],press:7,pretti:[5,7],prevent:7,price:5,primari:4,primit:7,priv:5,privaci:7,privat:[4,5,7],probabl:[0,7],problem:[5,7],proce:5,process:[3,7],produc:[5,7,8],product:[1,2,7],profit:[7,8],program:[3,4,7],programref:7,progress:5,project:0,proof:[1,4],propag:[1,7],properti:7,protect:5,protocol:[2,3,4],protocolstatemachin:5,prove:[1,4,6,7],provid:[3,4,5,7],ptx:5,publickei:[5,7],pull:0,pump:3,purchas:5,pure:4,purpos:[4,7],put:[5,7],qualiti:1,quantiti:[4,7],queue:3,quickli:[3,7],quit:[5,7],r3cev:5,random63bitvalu:5,random:[4,5],rapid:2,rather:[4,5,7],rational:4,reachabl:5,read:[1,2,4,5,7],readabl:4,reader:7,readi:7,real:[2,3,7],realism:3,realiti:7,realli:[5,7],reason:[5,7],reassign:7,receiv:[3,4,5,7,8],recipi:[3,7],recognis:7,record:[6,7],recreat:5,red:0,redeem:[4,7,8],redempt:[7,8],redemptiontim:[7,8],ref:[5,7],refer:[4,5,7],refin:4,reflect:7,refus:0,regist:[3,5],registr:3,registri:4,regular:[4,5,7],reissuanc:7,reject:7,rel:4,relat:[5,7],relationship:7,releas:8,relev:4,reli:4,reliabl:3,relianc:4,remain:[7,8],rememb:[5,7],remov:[3,7],render:8,repeat:3,replac:7,replic:4,report:[3,6],repres:[3,4,5,7],request:5,requir:[3,4,6],requiresinglecommand:7,requirethat:[5,7],resolut:[1,4,6],resolv:[5,6],resourc:5,respect:7,respons:5,rest:[3,4],restart:[0,5],restor:5,result:[4,5,7],resultfutur:5,resum:5,resurrect:5,retri:3,reus:5,reveal:7,rewrit:5,rfc:4,right:[0,3,5],rigid:4,risk:5,roadmap:[],roll:6,rollov:7,room:5,root:[7,8],rout:[5,6],router:3,rule:[5,7],run:[0,3,4,5,7],runawai:6,runbuy:5,runnetwork:3,runsel:5,runtim:6,safe:[4,5,6,7],sai:[4,7],sale:7,same:[3,4,5,7,8],sandbox:[2,4,6,7],saniti:5,satisfi:[5,7],save:7,scala:[4,7],scalabl:[4,7],scene:[5,7],scope:[4,7],screen:0,script:[4,7],seamless:4,search:[0,7],second:[5,7],secondari:5,secp256r1:2,section:7,secur:[3,4,5],securehash:7,see:[3,5,6,7],seen:[6,7,8],select:[0,7],sell:[5,7],seller:[],sellerimpl:5,sellerinitialarg:5,sellerownerkei:5,sellertradeinfo:5,semi:4,send:[3,4,5,7],sendandrec:5,sens:[5,7],sent:[3,5,7],separ:[5,6,7],sequenc:3,sequenti:5,serial:[2,7],serialis:[2,3,4,5,7],serializablewithkryo:7,serializeablewithkryo:7,server:6,servic:[3,5],servicehub:5,session:[3,5],sessionid:5,setter:7,settl:3,settlement:5,sever:[4,5,7],sha256:7,sha:4,share:[1,4,5,7],she:7,shortcut:2,shorthand:7,shot:3,should:[0,2,3,4,5,6,7],shouldn:5,show:[0,4,7,8],shown:7,shutdown:5,side:5,sig:[5,7],sign:[2,4,5,7],signatur:[2,4,5,6,7],signedwiretransact:[5,7],signer:7,signwith:[5,7],signwithecdsa:5,similar:[4,7],similarli:7,simpl:[3,5,7,8],simpler:4,simplest:5,simpli:[3,5,7],simplifi:[2,3,4,7],simultan:[3,5,7],singl:[4,5,7,8],singlemessagerecipi:[3,5],singleton:7,sit:3,site:6,size:[5,7],skeleton:5,slight:7,slightli:7,small:[2,4,5,7,8],smart:2,smm:5,smooth:7,snippet:7,softwar:2,sold:[5,7,8],solv:[5,7],some:[2,3,4,5,6,7,8],somed:7,someon:[3,7],someprofit:[7,8],someth:[0,5,7],sometim:[3,4,7],somewhat:4,somewher:[7,8],sort:[4,5],sound:[5,7,8],sourc:5,space:7,special:[],specif:[3,4,5,7,8],specifi:[2,3,7],speed:5,spend:[4,5,6,7],split:[4,7],spread:[3,5],squar:8,src:[7,8],stack:5,stage:[5,6,7],stai:4,standard:[1,4,7],standardis:[4,7],start:[],state:[3,4],stateandref:[5,7],stateless:4,statemachinemanag:5,statement:[5,7],stateref:[4,5],statesoftyp:5,step:[5,6,7],still:[4,7],stop:[3,5,6],storag:[4,6],store:[5,7],straight:[],straightforward:[5,7],stream:5,string:[3,5,7],strong:4,structur:[0,2,4,5,7],studi:7,stuff:5,stx:5,style:3,subgraph:6,subgroup:4,submenu:0,successor:4,suffici:[1,3],suffix:7,suggest:7,suitabl:6,sum:7,sumcashbi:[5,7],sumcashornul:7,summaris:4,superclass:5,supertyp:7,support:[4,5,6,7],suppos:[5,7],sure:[5,7],surround:7,surviv:5,suspend:5,swap:5,symbol:0,synchronis:4,syntax:[4,7],system:[2,4,5,6,7],tab:0,tailor:1,take:[2,5,7,8],target:4,targetrecipi:3,task:[4,5,6],techniqu:7,tell:3,tempor:6,temporarili:5,tempt:7,temptat:5,ten:7,term:[4,7],termin:5,terminolog:4,test:[0,2,3,4,6],test_tx_tim:7,testutil:7,testwithinmemorynetwork:3,text:0,than:[1,4,5,7,8],thei:[3,4,5,6,7],them:[2,3,5,7],themselv:[3,4,7],theori:[],therefor:[2,4,7],thesi:6,thi:[0,1,3,4,5,6,7,8],thing:[2,4,5,6,7],think:[0,5,7],third:[5,7],those:[3,7],though:[3,5,7],thought:4,thread:[3,5,6],three:[2,7],threshold:7,through:[4,5,6,7],thrown:7,thu:7,tighten:7,tightli:5,time:[4,5,6,7,8],timelin:7,timestamp:[4,5,7],timestampedwiretransact:5,timestampingservic:5,todo:[5,7],togeth:[4,7],too:[5,7,8],took:5,tool:4,top:[5,7],topic:[3,5],topriv:5,tosignedtransact:[5,7],tostr:7,total:7,totimestampedtransact:5,trace:5,track:5,tracker:2,trade:4,trade_top:5,traderequest:5,tradit:7,traffic:5,transact:[1,4,5,6,7,8],transactionforverif:7,transactiongroup:[5,7],transactiongroupdsl:8,transactiongroupfor:8,transactiongroupfortest:7,transfer:7,transit:[1,7],treat:7,tri:7,trick:5,tricki:5,tripl:4,truth:5,tsa:4,tsp:4,ture:4,turn:[5,7],tutori:[2,4],twice:4,two:[3,4],twopartytradeprotocol:5,twopartytradeprotocolimpl:5,txbit:5,txhash:[4,7],type:[4,5,7],typetobui:5,typic:[3,5,7],unacceptablepriceexcept:5,under:7,underscor:7,understand:3,unexecut:7,unfinsish:5,unfortun:[5,7],unguess:5,uniqu:4,unit:[0,2,3,4,5,7,8],unless:[5,7],unlik:7,unnecessari:7,unpack:5,unread:5,unrecognis:7,unsaf:6,unserialis:5,unspent:4,unsupportedoperationexcept:7,until:[3,5],unus:3,unusu:7,unwieldi:7,updat:[0,4,5,7],upgrad:[0,1,6],upload:6,upon:[4,7],url:0,usabl:4,usag:7,user:[2,3,4,5],util:[3,4,7],utxo:4,val:[3,5,7,8],valid:[4,5,6,7],valu:[4,7,8],vari:7,variabl:[5,7],variant:7,variou:[4,5,7],vendor:2,verbos:7,veri:[4,8],verif:[2,4],verifi:[2,4,6],verifysignatur:5,verifytoledgertransact:5,versa:5,version:[0,2,5,7],versu:5,via:5,vice:5,virtual:[1,4],visibl:4,visualis:[],vote:6,wai:[4,5,6,7],wait:[0,3,5],wallet:[4,5,7],walletservic:5,wan:6,want:[0,3,5,7],websit:7,well:[2,4,5,7],were:[5,7],what:[],whatev:5,when:[3,5,6,7],where:[3,4,5],wherea:7,whether:3,which:[2,3,4,5,7],whilst:[4,5,7],who:[3,4,5,7],whole:7,why:[4,5,7],wide:[3,7],wiki:[4,7],wikipedia:7,window:8,wire:5,wirecommand:[5,7],wiretransact:5,wish:[3,5,6,7],within:4,withnewown:5,withoutown:7,won:[3,7],work:[0,1,2,3,4,5,7],world:[5,7],worn:7,worri:[4,5],worth:7,would:[2,3,5,7],wouldn:7,wrap:7,wrapper:5,write:[4,5,7],written:[4,7],wtx:5,www:0,yet:[4,7],yield:4,you:[0,2,3,4,5,7,8],your:3,your_usernam:0,zero:7},titles:["Getting set up","Welcome to the R3 prototyping repository!","What’s included?","Networking and messaging","Overview","Protocol state machines","Roadmap","Tutorial","Using the visualiser"],titleterms:{"class":7,"function":7,about:0,api:7,asset:7,base:7,bitcoin:4,buyer:5,check:7,command:7,commerci:7,comparison:4,complain:0,contract:[4,7],craft:7,data:4,ethereum:4,fungibl:7,get:0,how:7,implement:[3,5],includ:2,intellij:0,interfac:3,introduct:5,kotlin:4,lack:0,machin:5,manag:5,memori:3,messag:3,model:4,network:3,non:7,orient:7,overview:4,paper:7,parti:5,protocol:5,prototyp:1,repositori:1,requir:7,roadmap:6,sdk:0,seller:5,set:0,smart:7,start:7,state:[5,7],test:7,theori:5,trade:5,tutori:7,two:5,understand:7,verifi:7,visualis:8,welcom:1,what:2,without:0,your:7}}) \ No newline at end of file diff --git a/docs/source/protocol-state-machines.rst b/docs/source/protocol-state-machines.rst index 21c34d4e66..69705fe896 100644 --- a/docs/source/protocol-state-machines.rst +++ b/docs/source/protocol-state-machines.rst @@ -57,7 +57,7 @@ Theory A *continuation* is a suspended stack frame stored in a regular object that can be passed around, serialised, unserialised and resumed from where it was suspended. This may sound abstract but don't worry, the examples below -will make it clearer. The JVM does not natively support continuations, so we implement them using a a library called +will make it clearer. The JVM does not natively support continuations, so we implement them using a library called JavaFlow which works through behind-the-scenes bytecode rewriting. You don't have to know how this works to benefit from it, however. @@ -150,12 +150,12 @@ Let's unpack what this code does: and returns it, with a ``StateMachineManager`` as an instance. The Impl class will be defined below. .. note:: Session IDs keep different traffic streams separated, so for security they must be large and random enough -to be unguessable. 63 bits is good enough. + to be unguessable. 63 bits is good enough. 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 ``.get()`` 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. +to either runBuyer or runSeller, depending on who we are, and then call ``.resultFuture.get()`` on resulting object 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. The only tricky part is how to get one of these things. We need a ``StateMachineManager``. Where does that come from and why do we need one? @@ -221,7 +221,8 @@ It could be as simple as a chat room or as complex as a 24/7 exchange. .. sourcecode:: kotlin - // This object is serialised to the network and is the first protocol message the seller sends to the buyer. + // This object is serialised to the network and is the first protocol message + // the seller sends to the buyer. class SellerTradeInfo( val assetForSale: StateAndRef, val price: Amount, @@ -244,11 +245,11 @@ Next we add some code to the ``SellerImpl.call`` method: // Make the first message we'll send to kick off the protocol. val hello = SellerTradeInfo(args.assetToSell, args.price, args.myKeyPair.public, sessionID) - // Zero is a special session ID that is being listened to by the buyer (i.e. before a session is started). - val partialTX = sendAndReceive(TRADE_TOPIC, args.buyerSessionID, sessionID, hello) + val partialTX = sendAndReceive(TRADE_TOPIC, args.buyerSessionID, + sessionID, hello) logger().trace { "Received partially signed transaction" } -That's pretty straight forward. We generate a session ID to identify what's happening on the seller side, fill out +That's pretty straightforward. We generate a session ID to identify what's happening on the seller side, fill out the initial protocol message, and then call ``sendAndReceive``. This function takes a few arguments: - A type argument, which is the object we're expecting to receive from the other side. @@ -347,16 +348,18 @@ OK, let's do the same for the buyer side: if (!args.typeToBuy.isInstance(tradeRequest.assetForSale.state)) throw AssetMismatchException(args.typeToBuy.name, assetTypeName) - // TODO: Either look up the stateref here in our local db, or accept a long chain of states and - // validate them to audit the other side and ensure it actually owns the state we are being offered! - // For now, just assume validity! + // TODO: Either look up the stateref here in our local db, or accept a long chain + // of states and validate them to audit the other side and ensure it actually owns + // the state we are being offered! For now, just assume validity! // Generate the shared transaction that both sides will sign, using the data we have. val ptx = PartialTransaction() - // Add input and output states for the movement of cash, by using the Cash contract to generate the states. + // Add input and output states for the movement of cash, by using the Cash contract + // to generate the states. val wallet = serviceHub.walletService.currentWallet val cashStates = wallet.statesOfType() - val cashSigningPubKeys = Cash().craftSpend(ptx, tradeRequest.price, tradeRequest.sellerOwnerKey, cashStates) + val cashSigningPubKeys = Cash().craftSpend(ptx, tradeRequest.price, + tradeRequest.sellerOwnerKey, cashStates) // Add inputs/outputs/a command for the movement of the asset. ptx.addInputState(tradeRequest.assetForSale.ref) // Just pick some new public key for now. @@ -378,14 +381,17 @@ OK, let's do the same for the buyer side: 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. + // 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(TRADE_TOPIC, tradeRequest.sessionID, args.sessionID, stx) logger().trace { "Got fully signed transaction, verifying ... "} - val ltx = fullySigned.verifyToLedgerTransaction(serviceHub.timestampingService, serviceHub.identityService) + val ltx = fullySigned.verifyToLedgerTransaction(serviceHub.timestampingService, + serviceHub.identityService) logger().trace { "Fully signed transaction was valid. Trade complete! :-)" } @@ -396,7 +402,8 @@ OK, let's do the same for the buyer side: This code is fairly straightforward. Here are some things to pay attention to: 1. We do some sanity checking on the received message to ensure we're being offered what we expected to be offered. -2. We create a cash spend in the normal way, by using ``Cash().craftSpend``. +2. We create a cash spend in the normal way, by using ``Cash().craftSpend``. See the contracts tutorial if this isn't + clear. 3. We access the *service hub* 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 @@ -411,6 +418,6 @@ the fact that it takes minimal resources and can survive node restarts. 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 ``serviceHub`` field is defined by the ``ProtocolStateMachine`` 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 + this problem doesn't occur. It's also restored for you when a protocol state machine is restored after a node restart.