Trubanc in Plain English

Trubanc is an anonymous, digitally-signed vault and trading system. Like Loom, it allows anyone to issue assets (digital currencies). Unlike Loom, which relies entirely on (very good) obscurity for security, Trubanc's digital signatures allow the bank and the customer to prove to each other that they agreed at a particular time on their balances. It does this while allowing destruction of transaction history for closed trades. Trubanc will initially provide server-based trading. Eventually, it will provide digital checks and bearer certificates. These, however, WILL require permanent storage of transaction history (unless they expire).

doc/db.txt gives a terse description of the Trubanc server database and protocol. This page attempts to render the protocol in plain English.

Trubanc uses public key cryptography to sign all messages passed back and forth between its web interface and the Trubanc server. Digital signatures are a virtually unforgeable way to ensure that a message was written by its purported author. Trubanc uses OpenSSL for its public key cryptography. You probably use OpenSSL every time you visit a secure web site, https://somewhere.com/, as does the web server. I didn't roll my own. Just used the same tried and true technology that secures the web. You can read more about public key cryptography, digital signatures, and hashing here and here.

I'm going to use four actors in the scenarios that follow. "Bank" is the name of the Trubanc server. "Bob" and "Sue" are two customers, who will trade with each other. "Spammer" is a third customer, unknown to Bob or Sue.

Scenario: Opening an Account

Sue (via email or IM): Hey, Bob. Check out Trubanc. Go to Trubanc.com, download the client, and install it on your computer. Then create a private key, and send me your ID, and I'll give you some usage tokens so that you can create an account.

Bob (via email or IM): Thanks, Sue! I installed the Trubanc client and created a private key. Here's my ID.

Sue (via her Trubanc client): Hey bank, Here's a new request number. Give me a transaction number please.
Signed: Sue

Bank: Here's a new transaction number.
Signed: Bank

Sue: Hey bank, here's that transaction number you gave me. Please spend 50 usage tokens to Bob's ID, with a message of "Hey Bob. Welcome to Trubanc!" I'm paying 2 usage tokens as a transaction fee, which I'll get back when Bob accepts the spend. My balance after this transaction will be 1025 usage tokens. My outbox hash after this transaction will be X.
Signed: Sue

Bank: I processed your spend of 50 usage tokens to Bob's ID. I agree that the transaction fee at the time of this transaction is 2 usage tokens, and that your balance after this transaction is 1025 usage tokens. I agree with you on your outbox hash.
Signed: Bank

Sue (via email or IM): OK, Bob. I've given you 50 usage tokens. You should now be able to create an account at Trubanc.com. Send me a message via Trubanc when you've registered.

Bob (via his Trubanc client): Hello bank. Here's my ID and my public key. What's your ID and public key?
Signed: Bob

Bank: Here's my ID and public key.
Signed: Bank

Bob: Here's my ID and my public key, please create an account for me.
Signed: Bob

Bank: I've registered your ID and public key. Somebody gave you enough tokens to register. Welcome to Trubanc.
Signed: Bank

-----

In order to sign a message, you need to have a private key. In order to verify the signature on a message, you need to have the corresponding public key. Trubanc identifies customers by the hash of their public key, their ID. The ID is a 40-character string of numbers and the letters A to F, the hexadecimal representation of a 160-bit number. You identify your account to the Trubanc client with a passphrase, which is used to encrypt your private key on your disk. You'll only need to copy and paste your ID when you want to tell a trading partner how to send you money for the first time, or to seed your account with usage tokens, as Sue did for Bob.

Usage tokens are an idea from Patrick Chkoreff's Loom system. They are a way to charge for the bank's resources. You have to buy storage for your account balances, and lease temporary storage for transactions. Usage tokens are the "currency" used to do this. Trubanc also supports fees in other asset types, for bank management that wants to make more than the sale of usage tokens. Trubanc uses the file system as a database. One file in the Trubanc database costs one usage token. Files vary in size, but are usually about 8K, mostly signatures.

Note that Bob had to send his public key to the bank twice, once when he requested the bank's public key, and again when he registered. Every message going to and from Trubanc is digitally signed. It's only possible to verify a digital signature if you know the public key of the signer. A new customer's public key isn't in the database until after he's registered, so the first two messages, in which the new customer gets the bank's public key, so that he can verify the bank's signatures, and the registration request, both need to include the customers's public key, so that the signatures on those two messages can themselves be verified. After registration is complete, subsequent messages need to carry only the ID; the public key can then be looked up in the database.

Actual messages sent (with the signature that goes with each parenthesized item omitted):

Sue: (<suesid>,gettime,<bankid>,<req#>)
Bank: (<bankid>,time,<suesid>,<time#>)
Sue: (<suesid>,spend,<bankid>,<time#>,<bobsid>,<tokenid>,50,Hey Bob\. Welcome to Trubanc!).
        (<suesid>,tranfee,<bankid>,<time#>,<tokenid>,2).
        (<suesid>,balance,<bankid>,<time#>,<tokenid>,1025).
        (<suesid>,outboxhash,<bankid>,<time#>,X)
Bank: (<bankid>,@spend,(<suesid>,spend,<bankid>,<time#>,<bobsid>,<tokenid>,50,Hey Bob\. Welcome to Trubanc!)).
        (<bankid>,@tranfee,(<suesid>,tranfee,<bankid>,<time#>,<tokenid>,2)).
        (<bankid>,@balance,(<suesid>,balance,<bankid>,<time#>,<tokenid>,1025)).
        (<bankid>,@outboxhash,(<suesid>,outboxhash,<bankid>,<time#>,X))
Bob: (<bobsid>,bankid,<pubkey>)
Bank: (<bankid>,register,<bankid>,<pubkey>,Trubanc)
Bob: (<bobsid>,register,<bankid>,<pubkey>,Bob)
Bank: (<bankid>,@register,(<bobsid>,register,<bankid>,<pubkey>,Bob))

Scenario: Receiving Assets

Bob: Hello bank. Here's my ID and a new request number. What's in my inbox?
Signed: Bob

Bank: Your inbox contains a 50 usage token spend from Sue with a message of "Hey Bob. Welcome to Trubanc!" It also contains a 10 usage token charge from the bank with a message of "Registration Fee". Here are two transaction numbers you can use to accept these spends and do a spend yourself.
Signed: Bank

Bob: Here's my ID and the first of the transaction numbers you gave me. Accept the spend from Sue with a message of, "Thanks, Sue. I'm excited about Trubanc!" Accept the bank charge. My balance after this transaction will be 39 usage tokens.
Signed: Bob

Bank: I've processed the spend from Sue and the bank charge. I agree that your balance after this transaction is 39 usage tokens.
Signed: Bank

-----

One possible attack on an electronic bank can be for someone to replay an intercepted message. Unless the protocol protects against that, this can cause problems. Except for the bankid request, the registration request, and a request for a customer's last request number, every information request must be accompanied by a request number that is larger than the customer's last used request number, and every transaction must be accompanied by a transaction number that is given out by the bank. The bank maintains a counter, which it increments each time someone asks for a transaction number. This makes requests that reveal information or initiate transactions impossible to replay without a customer's passphrase and private key. In the Trubanc world, your passphrase and your private key are your identity. Guard them well.

Another possible replay attack is to intercept a message for one bank and send it to another. Customers could protect against this by having different IDs, hence different public/private key pairs, for different banks. But it will be very convenient to use the same ID. Your friends will recognize you, and you'll have only one passphrase to remember. So the bank's ID is included in almost every request. Requests meant for another bank will not work.

You're probably wondering why Bob's balance after the transaction is 39, instead of 40, usage tokens. He got 50 usage tokens from Sue, and paid the bank 10 usage tokens for his registration fee. The additional usage token is the price of the new file used to store the usage token balance. Storage costs usage tokens. Loom charges 1 usage token for each 16 bytes of storage. I considered charging per byte, but decided that charging per file was easier to handle, though not quite as fair. It only makes sense if message sizes are limited, of course. If you were allowed megabyte messages, then Trubanc would have to charge per byte, or per kilobyte.

Actual messages sent:

Bob: (<bobsid>,getinbox,<bankid>,<req#>)
Bank: (<bankid,@getinbox,(<bobsid>,getinbox,<bankid>,<req#>)).
        (<bankid>,inbox,<time3#>,(<suesid>,spend,<bankid>,<time#>,<bobsid>,<tokenid>,50,Hey Bob\. Welcome to Trubanc!)).
        (<bankid>,inbox,<time4#>,(<bankid>,spend,<bankid>,<time2#>,<bobsid>,<tokenid>,-10,Registration Fee)).
        (<bankid>,time,<bobsid>,<time5#>).
        (<bankid>,time,<bobsid>,<time6#>)
Bob: (<bobsid>,processinbox,<bankid>,<time5#>,<time3#>|<time4#>).
       (<bobsid>,spend|accept,<bankid>,<suesid>,<time#>,Thanks Sue\. I'm excited about Trubanc!).
       (<bobsid>,spend|accept,<bankid>,<bankid>,<time2#>).
       (<bobsid>,balance,<bankid>,<time5#>,<tokenid>,39)
Bank: (<bankid>,@processinbox,(<bobsid>,processinbox,<bankid>,<time5#>,<time3#>|<time4#>)).
        (<bankid>,@spend|accept,(<bobsid>,spend|accept,<bankid>,<suesid>,<time#>,Thanks Sue\. I'm excited about Trubanc!)).
        (<bankid>,@spend|accept,(<bobsid>,spend|accept,<bankid>,<bankid>,<time2#>)).
        (<bankid>,@balance,(<bobsid>,balance,<bankid>,<time5#>,<tokenid>,39))

Scenario: Closing a Transaction

Sue: Hello bank. Here's my ID and a new request number. What's in my inbox?
Signed: Sue

Bank: Your inbox contains an acceptance from Bob of your 50 usage token spend with a message of, "Thanks Sue. I'm excited about Trubanc!" Here are two transaction numbers you can use to close that transaction and do a new spend.
Signed: Bank

Sue: Here's my ID and the first of the transaction numbers you gave me. Clear the spend to Bob. My balance after this transaction will be 1027 usage tokens. My outbox hash after this transaction will be Y.
Signed: Sue

Bank: I've cleared the spend to Bob (and refunded the usage tokens that were leasing the outbox and inbox locations). I agree that your balance after this transaction is 1027 usage tokens. And I agree that your outbox hash after this transaction is Y.
Signed: Bank

-----

There are three main parts of a Trubanc account: the balances, the outbox, and the inbox. Value is stored in all three places. When you do a spend, your balance for the spent asset is debited, and the spend request is stored in your outbox and in the recipients inbox. You are charged two usage tokens to lease the new outbox and inbox files. When the recipient accepts the spend, his balance for the spent asset is credited, the spend notice is removed from his inbox, and a spend acceptance notice is added to your inbox. When you acknowledge his acceptance of the spend, the spend request is removed from your outbox, the acceptance notice is removed from your inbox, and the two usage tokens you paid to lease those files is credited to your balance. This three step process is necessary, because the bank can't modify your balances without your signed permission, and it can't modify the recipient's balances without his signed permission.

You may be wondering what an "outbox hash" is. Your balances plus your outbox represent the part of your account that you and the bank have agreed upon. Your inbox is changed without your knowledge, but the bank needs your signed permission to change your outbox (do a spend) or your balances. Since your outbox might get large, instead of sending the entire contents back and forth every time you do a spend, or acknowledge the acceptance (or rejection) of a spend by a recipient, you compute a hash of your outbox, and send that instead, and the bank responds with an acknowledgement of that outbox hash (thank you to Patrick Chkoreff for this idea).

Actual messages sent:

Sue: (<suesid>,getinbox,<bankid>,<req2#>)
Bank: (<bankid,@getinbox,(<suesid>,getinbox,<bankid>,<req2#>)).
        (<bankid>,inbox,<time7#>,(<bobsid>,spend|accept,<bankid>,<suesid>,<time#>,Thanks Sue\. I'm excited about Trubanc!)).
        (<bankid>,time,<bobsid>,<time8#>).
        (<bankid>,time,<bobsid>,<time9#>)
Sue: (<suesid>,processinbox,<bankid>,<time8#>,<time7#>).
       (<suesid>,balance,<bankid>,<time8#>,<tokenid>,1027).
       (<suesid>,outboxhash,<bankid>,<time8#>,Y)
Bank: (<bankid>,@processinbox,(<suesid>,processinbox,<bankid>,<time8#>,<time7#>)).
        (<bankid>,@balance,(<suesid>,balance,<bankid>,<time8#>,<tokenid>,1027)).
        (<bankid>,@outboxhash,(<suesid>,outboxhash,<bankid>,<time8#>,Y))

Scenario: Preventing Spam

Spammer (likely via an automated client): Hey bank. Here's a new request number. Give me a transaction number please.
Signed: Spammer

Bank: Here's a new transaction number.
Signed: Bank

Spammer: Hey bank. Here's that transaction number you gave me. Please spend 0 usage tokens to Bob's ID, with a message of, "Go all night. Visit BuyViagra.com." I'm paying 2 usage tokens as a transaction fee, which I'll get back when Bob accepts the spend. My balance after this transaction will be 2425 usage tokens. My outbox hash after this transaction will be Z.
Signed: Spammer

Bank: I processed your spend of 0 usage tokens to Bob's ID. I agree that the transaction fee at the time of this transaction is 2 usage tokens, and that your balance after this transaction is 2425 usage tokens. I agree with you on your outbox hash.
Signed: Bank

Bob: Hello bank. Here's my ID and a new request number. What's in my inbox?
Signed: Bob

Bank: Your inbox contains a 0 usage token spend from Spammer with a message of, "Go all night. Visit BuyViagra.com." Here are two transaction numbers you can use to accept these spends and do a spend yourself.
Signed: Bank

Bob: Here's my ID and the first of the transaction numbers you gave me. Reject the spend from Spammer with a message of, "Thanks for the tokens", and give me the two usage tokens he paid to send that spam. My balance after this transaction will be 41 usage tokens.
Signed: Bob

Bank: I've rejected the spend from Spammer. I agree that your balance after this transaction is 41 usage tokens.
Signed: Bank

-----

Spends can be rejected. The amount spent goes back to the spender, but the recipient pockets the transaction fee. Zero spends use Trubanc as a simple messaging service. But not a free one, unless the recipient wants the message. IMHO, spam exists largely because it is nearly free to send email. In a system where each spam message costs 2 usage tokens, cheap but not free, I doubt it will be much of a problem. Time will tell.

Actual messages sent:

Spammer: (<spammersid>,gettime,<bankid>,<req#>)
Bank: (<bankid>,time,<spammersid>,<time10#>)
Spammer: (<spammersid>,spend,<bankid>,<time10#>,<bobsid>,<tokenid>,0,Go all night\. Visit BuyViagra.com\.).
        (<spammersid>,tranfee,<bankid>,<time#>,<tokenid>,2).
        (<spammersid>,balance,<bankid>,<time#>,<tokenid>,2425).
        (<spammersid>,outboxhash,<bankid>,<time#>,Z)
Bank: (<bankid>,@spend,(<spammersid>,spend,<bankid>,<time#>,<bobsid>,<tokenid>,0,Go all night\. Visit BuyViagra.com\.)).
        (<bankid>,@tranfee,(<spammersid>,tranfee,<bankid>,<time#>,<tokenid>,2)).
        (<bankid>,@balance,(<spammersid>,balance,<bankid>,<time#>,<tokenid>,2425)).
        (<bankid>,@outboxhash,(<spammersid>,outboxhash,<bankid>,<time#>,Z))
Bob: (<bobsid>,getinbox,<bankid>,<req2#>)
Bank: (<bankid,@getinbox,(<bobsid>,getinbox,<bankid>,<req2#>)).
        (<bankid>,inbox,<time11#>,(<spammersid>,spend,<bankid>,<time10#>,<bobsid>,<tokenid>,0,Go all night\. Visit BuyViagra.com\.)).
        (<bankid>,time,<bobsid>,<time12#>).
        (<bankid>,time,<bobsid>,<time13#>)
Bob: (<bobsid>,processinbox,<bankid>,<time12#>,<time11#>).
       (<bobsid>,spend|reject,<bankid>,<spammersid>,<time12#>,<time10#>,Thanks for the tokens).
       (<bobsid>,balance,<bankid>,<time12#>,<tokenid>,41)
Bank: (<bankid>,@processinbox,(<bobsid>,processinbox,<bankid>,<time12#>,<time11#>)).
        (<bankid>,@spend|reject,(<bobsid>,spend|accept,<bankid>,<spammersid>,<time12#>,<time10#>,Thanks for the tokens)).
        (<bankid>,@balance,(<bobsid>,balance,<bankid>,<time12#>,<tokenid>,41))

Scenario: Issuing Assets

Bob: Hey bank. Here's a new request number. Give me a transaction number please.
Signed: Bob

Bank: Here's a new transaction number.
Signed: Bank

Bob: Hey bank. Here's that transaction number you gave me. Please register a new asset named "Bob GoldGrams". It has a scale of 7 and a precision of 3. Its ID is <bobggid>. My balance after this transaction will be 39 usage tokens and -1 <bobggid>.

Bank: I have registered the new "Bob GoldGrams" asset. I agree that your balance after this transaction is 39 usage tokens and -1 <bobggid>.

-----

Like Loom, Trubanc allows customers to create their own asset types. Then, if they can convince them to do so, other customers can trade in that asset type. The ID of a Trubanc asset is the sha1 hash of the creator's ID, its scale, its precision, and its name. But the message the customer signs to create the asset, and that the bank signs to acknowledge creation, also contains the bankid. This allows the asset to be registered at multiple banks, with the same ID, but makes each particular registration specific to a specific bank. Hence, it makes sense for an asset issuer to provide a service of transferring his holdings of his asset between banks at which he's registered; it's self-evident that Bob GoldGrams at Bank A are the same asset as Bob GoldGrams at bank B.

I plan to support transfer of asset issuance, but I haven't figured out the intricacies yet.

Like Loom, all amounts in Trubanc are stored as integers. The scale value controls where the decimal point goes in the real-world representation of that value: move it left by scale places. The precision controls the minimum number of decimal places that are printed. So with a scale of 7 and a precision of 3, the value 12000000 will be printed by Trubanc clients as 1.200, and the minimum value for Bob's new currency is 0.0000001, one ten-millionth of a gram of gold, or $0.000003 at $30/gram: 3 ten-thousandths of a cent. Hello micropayments.

Also like Loom, the sum of all the amounts, in accounts and outboxes, for one asset type is -1. There is one negative balance, owned by the issuer, who can spend as much as he wants, and a bunch of positive balances, and outbox entries. A -1 balance in the issuer's account means there are no outstanding balances or outbox entries in that asset, so that's where Bob's Bob GoldGrams balance begins. Users of an asset have to trust the issuer when he tells them, outside of Trubanc, that his asset is backed by something of real value, and that he'll never issue more of the virtual asset than he has in the backing commodity. Well, unless he wants to act like a country, and issue fiat currency that is backed by his Full Faith and Credit and nothing else. Good luck getting people to go for that.

Actual messages sent:

Bob: (<bobsid>,gettime,<bankid>,<req3#>)
Bank: (<bankid>,time,<bobsid>,<time13#>)
Bob: (<bobsid>,asset,<bankid>,<bobggid>,7,3,Bob GoldGrams).
       (<bobsid>,balance,<bankid>,<time13#>,<tokenid>,39).
       (<bobsid,balance,<bankid>,<time13#>,<bobggid>,-1)
Bank: (<bankid>,#asset,(<bobsid>,asset,<bankid>,<bobggid>,7,3,Bob GoldGrams)).
       (<bankid>,#balance,(<bobsid>,balance,<bankid>,<time13#>,<tokenid>,39)).
       (<bankid>,#balance,(<bobsid,balance,<bankid>,<time13#>,<bobggid>,-1))

Scenario: Multiple Sub-Accounts

Bob: Hey bank. Here's a new request number. Give me a transaction number please.
Signed: Bob

Bank: Here's a new transaction number.
Signed: Bank

Bob: Hey bank. Here's that transaction number you gave me. Make a zero spend to myself. My balance after the transaction will be 38 usage tokens, -311.0347681 Bob GoldGrams in my default sub-account, and 311.034768 Bob GoldGrams in my "Gun Safe" sub-account.

Bank: I did that spend. I agree with you that after the transaction, your balance is 38 usages tokens, -311.0347681 Bob GoldGrams in your default account, and 311.034768 Bob GoldGrams in your "Gun Safe" sub-account.

Bob: Hey bank. Here's a new request number. Give me a transaction number please.
Signed: Bob

Bank: Here's a new transaction number.
Signed: Bank

Bob: Hey bank. Here's that transaction number you gave me. Please spend 2.4056304 Bob GoldGrams to Sue, with a message of, "Well, I finally issued my new currency, backed by Krugerands in my gun safe. I'm giving you a gram in thanks for turning me on to Trubanc, and 1.4056304 grams for 36 Capulin Coffee Units, which you said you'd sell me, so I can buy more of Daniel Fourwinds' fine coffee that we relished at your house the other day. I used a gold price of $796.60/ounce, Kitco's bid price this morning." My transaction fee will be 2 usage tokens. My balance after this transaction will be 36 usage tokens, and 309.6291376 Bob GoldGrams in my "Gun Safe" sub-account. My outbox hash after this transaction will be A.
Signed: Bob

Bank: I have done your spend of 2.4056304 Bob GoldGrams to Sue, with your message, and a transaction fee of 2 usage tokens. I agree that your balance after this transaction is 36 usage tokens, and 309.6291376 Bob GoldGrams in your "Gun Safe" sub-account. I agree on the outbox hash.
Signed: Bank

-----

Trubanc supports splitting up your balances into multiple "sub-accounts". Much like a conventional bank gives you a checking account and a savings account, you can use these sub-accounts to help manage your assets. You can have as many of them as you wish, limited only by having usage tokens to pay for the files.

Bob has decided to keep track of his Bob GoldGrams assets with a "Gun Safe" sub-account, with a balance recording how many grams of the gold in his safe have not yet been put into circulation. He seeds it with 10 ounces of gold, the part of his holdings that he's willing to sell. Then he spends some of it to Sue, asking for enough Capulin Coffee Units for two pounds of Capulin Coffee ($17.95 per pound, shipped).

Note that you don't have to mention all of your balances with every spend. You only mention the balances that change. Also notice that there's no transaction fee for spends to yourself. Moving assets between your sub-accounts costs only tokens for new files. No need for the outbox and inbox stuff.

Actual messages sent:

Bob: (<bobsid>,gettime,<bankid>,<req4#>)
Bank: (<bankid>,time,<bobsid>,<time14#>)
Bob: (<bobsid>,spend,<bankid>,<time14#>,<bobsid>,<bobggid>,0).
        (<bobsid>,balance,<bankid>,<time14#>,<bobggid>,-3110347681).
        (<bobsid>,balance,<bankid>,<time14#>,<bobggid>,3110347680,Gun Safe)
Bank: (<bankid>,@spend,(<bobsid>,spend,<bankid>,<time14#>,<bobsid>,<bobggid>,0)).
        (<bankid>,@balance,(<bobsid>,balance,<bankid>,<time14#>,<bobggid>,-3110347681)).
        (<bankid>,@balance,(<bobsid>,balance,<bankid>,<time14#>,<bobggid>,3110347680,Gun Safe))
Bob: (<bobsid>,gettime,<bankid>,<req5#>)
Bank: (<bankid>,time,<bobsid>,<time15#>)
Bob: (<bobsid>,spend,<bankid>,<time15#>,<suesid>,<bobggid>,24056304,Well\, I
      finally issued my new currency\, backed by Krugerands in my gun
      safe\. I'm giving you a gram in thanks for turning me on to Trubanc\,
      and 1\.4056304 grams for 36 Capulin Coffee Units\, which you said you'd
      sell me\, so I can buy more of Daniel Fourwinds' fine coffee that we
      relished at your house the other day\. I used a gold price of
      $796\.60/ounce, Kitco's bid price this morning\.).
       (<bobsid>,tranfee,<bankid>,<time15#>,<tokenid>,2).
       (<bobsid>,balance,<bankid>,<time15#>,<bobggid>,3096291376,Gun Safe).
       (<bobsid>,outboxhash,<bankid>,<time15#>,A)
Bank: (<bankid>,@spend,(<bobsid>,spend,<bankid>,<time15#>,<suesid>,<bobggid>,24056304,Well\, I
       finally issued my new currency\, backed by Krugerands in my gun
       safe\. I'm giving you a gram in thanks for turning me on to Trubanc\,
       and 1\.4056304 grams for 36 Capulin Coffee Units\, which you said you'd
       sell me\, so I can buy more of Daniel Fourwinds' fine coffee that we
       relished at your house the other day\. I used a gold price of
       $796\.60/ounce, Kitco's bid price this morning\.)).
       (<bankid>,@tranfee,(<bobsid>,tranfee,<bankid>,<time15#>,<tokenid>,2)).
       (<bankid>,@balance,(<bobsid>,balance,<bankid>,<time15#>,<bobggid>,3096291376,Gun Safe)).
       (<bankid>,@outboxhash,(<bobsid>,outboxhash,<bankid>,<time15#>,A))

Scenario: Getting Information

To be done

Scenario: Cancelling a Spend

To be done

Copyright © 2008 Bill St. Clair, All Rights Reserved