Disclaimer: I am currently working on my own decentralized exchange although I've tried my best to make this feedback balanced and accurate.
First, let me say this is a great project. I like your user interface, your centralized order book is a nice simple idea, and you seem like a competent developer. However I can't help but think you're glossing over the security concerns by making too many assumptions. Keep in mind, I do understand this is a prototype but as it stands this design won't work for real money (at least not very well) and here is why:
1. Transaction malleability. If the transaction that the refunds depend on is mutated the refund will be invalidated, potentially locking any funds up within the contract and leaving the contract vulnerable to extortion attacks. You suggest this problem is too costly to perform but let me say: that might not be the case. A particular paper comes to mind (0) in which researchers were able to double-spend zero confirmation transactions on the Bitcoin network by having vastly more connectivity than the victim and using that connectivity to propagate the double spend TX before the legitimate TX arrives. The attack works by exploiting the properties of the mempool, as nodes will only accept the first version of a transaction for any group of inputs. Now in the context of your exchange, an attacker could simply mutate (3) the "bond" TX and propagate it to the rest of the network / the majority of miners before your original transaction arrives (1) ( 8 ). This attack would not be expensive to perform and could be done with a few hundred $5 a month VPS'. Additionally, the attacker could vastly optimise his chance of success by monitoring multiple points on the network, thereby ensuring the attacker sees transactions at the earliest possible time.
Even if the attacker only succeeds in mutating less than 5% of transactions and your exchange's transactions constitute less than 0.00001% of that TX volume - that could still translate to quite a large number of users effected (4) and OP_CHECKLOCKTIMEVERIFY won't save you here. You seem to be assuming that once Bitcoin Core merges the patch that all your problems will go away, but this relies on the assumption that alt-coins will actually merge Bitcoin Core's patches and stay up to date when generally they don't. There are still patches that were made to Bitcoin core in 2012 that have yet to be merged with Litecoin and I'm guessing it's the same story with other alt-coins too. Thus, alt-coins that aren't forked after the patches are likely to remain vulnerable to TX malleability for years - possibly indefinitely.
Of course, you could fix this whole nasty problem in a day by adding fail-safe keys to your scheme, that way if the money is locked you can still mediate ... but if you decide to do that, you then have to worry about the security of the keys and you couldn't claim that your scheme was entirely trustless if full mediation was required.
2. Partial matching. From my understanding of your code there doesn't seem to be a mechanism for partial matching. In practice, this would mean that your users would have to wait for 8~ confirmations * confirm_time minutes (80 minutes for Bitcoin!) between every match (and large orders may require hundreds of them.) The problem comes from the fact that Bitcoin transactions are like hierarchical trees, that outputs must be spent in full, and that the distribution of amounts amongst outputs isn't guaranteed to be optimal for matching trades. Consequently, any given match - even for a small amount - could make 100% of the coins in your wallet unavailable until the contract was confirmed (which would make it incredibly painful to match trades.)
A proper exchange needs to support partial matching (5) to be able to efficiently match orders and I'd argue its even more important for "decentralized" exchanges as trades are already thousands of times slower than centralised exchanges because of the block chain.
3. Non-standard transactions. Since this is getting too long I'll just summarise this point: cross-chain contracts rely on non-standard transactions whose propagation is outright rejected on most alt-coins. The result is your contracts likely won't work on the main network and if it does: confirmation time will take hours rather than minutes. This is a huge issue because you can't fix the lack of transaction support with any coding patch. It's an immovable object built directly into the parameters of the network and the only way around is to be able to influence the miners directly into accepting your non-standard transactions. You probably won't have this problem on the Bitcoin side because the IsStandard() rules were recently relaxed (2), but on alt-coin I can see you pulling your hair out (6) (7)
tl; dr, your design has major problems that you need to fix. These are all problems I've had to address in my design so if this criticism comes off as too vague I'm happy to elaborate.
(0)
https://eprint.iacr.org/2012/248.pdf(1) There have been reports of widespread transaction mutation on the main network. An attacker might already have the capabilities I've discussed.
(2)
https://github.com/bitcoin/bitcoin/pull/4365/files(3) I have a five line function in my repo - literally five lines, and it will mutate transactions on most alt-coins:
def mutate_tx(tx_hex):
"""
Mutates a raw transaction using TX malleability in the scriptSig (specifically, the OP codes.) This function shouldn't be used beyond testing as it uses an ugly eval() hack.
https://en.bitcoin.it/wiki/Transaction_Malleability
"""
tx = CTransaction.deserialize(binascii.unhexlify(tx_hex))
script_sig = repr(tx.vin[0].scriptSig)[9:]
script_sig = eval("CScript([OP_1, OP_DROP, " + script_sig)
tx.vin[0].scriptSig = script_sig
return b2x(tx.serialize())
(4) I'd argue even 1 user effected would be bad since there's potentially no way to retrieve the money if the other side discards the key.
(5) A simple solution is to sort the order book in descending order but that still doesn't guarantee optimal matching.
(6) Tier-Nolan came up with a solution to this that only requires non-standard transactions on one side of the trade. The details are available here:
https://github.com/TierNolan/bips/blob/bip4x/bip-atom.mediawiki(7) I really like cats.
( 8 ) The window of time for such attacks would be possible depending on how close the attacker was on the network to the broadcasting node. If we assume around 50 - 400ms latency between hops, then the arrival time for the initial transaction would still make a double-spend possible given the current network propagation delays:
http://bitcoinstats.com/network/propagation/And now I'm done editing.