From 181c951fdaabd13007eb70c93f0207605b0cc598 Mon Sep 17 00:00:00 2001 From: Rjected Date: Fri, 24 May 2019 08:42:25 -0400 Subject: [PATCH] Specified auction matching, cleaned up TODOs Also no trailing whitespace --- CONTRIBUTING.md | 3 +- README.md | 2 +- benchclient/channelcmds.go | 1 - cmd/ocx/README.md | 2 +- crypto/rsw/rswtimelock_test.go | 45 +++++++++++++++++-- cxbenchmark/README.md | 8 ++-- cxbenchmark/matchingbenchmark_test.go | 1 - cxdb/cxdbsql/auctionqueries.go | 63 ++++++++++++++++++++++++--- cxrpc/README.md | 2 +- cxrpc/bankcmds.go | 2 - cxrpc/channelcmds.go | 1 - cxrpc/ordercmds.go | 3 -- cxserver/keymgmt.go | 38 ++++------------ cxserver/lightning.go | 2 - dextechsurvey.md | 34 +++++++-------- features.md | 56 ++---------------------- go.mod | 5 ++- go.sum | 31 ++++--------- match/auctionorder_test.go | 4 ++ match/price.go | 4 +- 20 files changed, 155 insertions(+), 152 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d43b36f..43c3593 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,11 +26,12 @@ If you don't know what to work on, here are some things that generally increase * Documentation for packages and other things * Updates to this document that may help other contributors or developers get started * Anything that fixes a TODO in the code - - If you find a TODO, feel free to create an issue for it! Sometimes they're just left there and get forgotten. Some TODOs might already be fixed, so if you create an issue and it turns out the TODO was out of date, then you probably shouldn't work on it. + - If you find a TODO, feel free to create an issue for it! Sometimes they're just left there and get forgotten. Some TODOs might already be fixed, so if you create an issue and it turns out the TODO was out of date, then you probably shouldn't work on it. ## Who is the maintainer? Currently, [rjected](https://github.com/rjected) is the maintainer. +You can contact them by [email!](dan@dancline.net) ## How can I get my pull request merged? diff --git a/README.md b/README.md index b5b7f32..9b720aa 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![Go Report Card](https://goreportcard.com/badge/github.com/mit-dci/opencx)](https://goreportcard.com/report/github.com/mit-dci/opencx) [![GoDoc](https://godoc.org/github.com/mit-dci/opencx?status.svg)](https://godoc.org/github.com/mit-dci/opencx) -OpenCX stands for Open Cryptocurrency eXchange, it's an open-source cryptocurrency exchange toolkit originally built to help understand what a decentralized exchange should be. It's meant to be modular enough so features that increase trustlessness in cryptocurrency exchange can be implemented and experimented with. Included are packages for lightning support, RPC, authentication via the NOISE protocol, and a Golang API supporting multiple forms of authentication. +OpenCX stands for Open Cryptocurrency eXchange, it's an open-source cryptocurrency exchange toolkit originally built to help understand what a decentralized exchange should be. It's meant to be modular enough so features that increase trustlessness in cryptocurrency exchange can be implemented and experimented with. Included are packages for lightning support, RPC, authentication via the NOISE protocol, and a Golang API supporting multiple forms of authentication. There is also a robust implementation of timed-release cryptography in the `crypto` package. *Pull requests and issues encouraged!* diff --git a/benchclient/channelcmds.go b/benchclient/channelcmds.go index 1f40ae5..1634575 100644 --- a/benchclient/channelcmds.go +++ b/benchclient/channelcmds.go @@ -7,7 +7,6 @@ import ( ) // GetLitConnection gets the lit con to pass in to lit. Maybe do this more automatically later on -// TODO: in order for all the trading to work properly we need to switch from names to pubkeys func (cl *BenchClient) GetLitConnection() (getLitConnectionReply *cxrpc.GetLitConnectionReply, err error) { getLitConnectionReply = new(cxrpc.GetLitConnectionReply) getLitConnectionArgs := &cxrpc.GetLitConnectionArgs{} diff --git a/cmd/ocx/README.md b/cmd/ocx/README.md index 3516eec..c98c040 100644 --- a/cmd/ocx/README.md +++ b/cmd/ocx/README.md @@ -1,4 +1,4 @@ # ocx -**ocx** is a command-line client for many RPC commands which OpenCX RPC packages support. +**ocx** is a command-line client for many RPC commands which OpenCX RPC packages support. **ocx** is currently compatible with both commands in `cxrpc` as well as some in `cxauctionrpc`, so it can be used for both servers running `fred` or `opencxd`. \ No newline at end of file diff --git a/crypto/rsw/rswtimelock_test.go b/crypto/rsw/rswtimelock_test.go index ec4f641..9a5ff3d 100644 --- a/crypto/rsw/rswtimelock_test.go +++ b/crypto/rsw/rswtimelock_test.go @@ -48,6 +48,20 @@ func createSolveConcurrentN(time uint64, n int, t *testing.T) { return } +func createSolveConcurrentNBench(time uint64, n int, b *testing.B) { + doneChan := make(chan bool, n) + for i := 0; i < n; i++ { + go createSolveBench2048A2Async(time, doneChan, b) + } + + // Wait for our things to return - there may be a better way to do this with select + for i := 0; i < n; i++ { + <-doneChan + } + + return +} + func createSolveConcurrent(time uint64, t *testing.T) { createSolveConcurrentN(time, runtime.NumCPU(), t) return @@ -76,6 +90,29 @@ func createSolveTest2048A2Async(time uint64, doneChan chan bool, t *testing.T) { return } +func createSolveBench2048A2Async(time uint64, doneChan chan bool, b *testing.B) { + key := make([]byte, 32) + copy(key[:], []byte(fmt.Sprintf("opencxcreatesolve%d", time))) + rswTimelock, err := New2048A2(key) + if err != nil { + b.Fatalf("There was an error creating a new timelock puzzle: %s", err) + } + puzzle, expectedAns, err := rswTimelock.SetupTimelockPuzzle(time) + if err != nil { + b.Fatalf("There was an error setting up the timelock puzzle: %s\n", err) + } + puzzleAns, err := puzzle.Solve() + if err != nil { + b.Fatalf("Error solving puzzle: %s\n", err) + } + if !bytes.Equal(puzzleAns, expectedAns) { + b.Fatalf("Answer did not equal puzzle for time = %d. Expected %x, got %x\n", time, expectedAns, puzzleAns) + } + + doneChan <- true + return +} + func createSolveBench2048A2(time uint64, b *testing.B) { key := make([]byte, 32) copy(key[:], []byte(fmt.Sprintf("opencxcreatesolve%d", time))) @@ -284,8 +321,8 @@ func TestTenMillion2048A2(t *testing.T) { return } -func TestHundredMillion2048A2(t *testing.T) { - createSolveTest2048A2(100000000, t) +func BenchmarkHundredMillion2048A2(b *testing.B) { + createSolveBench2048A2(100000000, b) return } @@ -299,8 +336,8 @@ func TestConcurrentMillion2048A2(t *testing.T) { return } -func TestConcurrentManyMillions2048A2(t *testing.T) { - createSolveConcurrentN(10000000, runtime.NumCPU(), t) +func BenchmarkConcurrentManyMillions2048A2(b *testing.B) { + createSolveConcurrentNBench(10000000, runtime.NumCPU(), b) return } diff --git a/cxbenchmark/README.md b/cxbenchmark/README.md index 4fe09b8..f75dfc5 100644 --- a/cxbenchmark/README.md +++ b/cxbenchmark/README.md @@ -27,7 +27,7 @@ Memory Device Type: DDR4 Speed: 2133 MT/s Manufacturer: SK Hynix - Part Number: HMA41GS6AFR8N-TF + Part Number: HMA41GS6AFR8N-TF Configured Memory Speed: 2133 MT/s Configured Voltage: 1.2 V @@ -37,7 +37,7 @@ Memory Device Type: DDR4 Speed: 2133 MT/s Manufacturer: SK Hynix - Part Number: HMA41GS6AFR8N-TF + Part Number: HMA41GS6AFR8N-TF Configured Memory Speed: 2133 MT/s Configured Voltage: 1.2 V ``` @@ -47,7 +47,7 @@ All tests are run on the regtest environment as well. ### Currently known limits: - If you try to use SQL injection you will succeed. The honor system is currently in place to protect against that vulnerability. - - From start to finish, with many thousands of blocks, it takes a while to sync up. + - From start to finish, with many thousands of blocks, it takes a while to sync up. ## Placing orders and matching @@ -106,7 +106,7 @@ NOTE: The benchmark requires users `tester` and `othertester` to have a bunch of Here are the results for combination tests. PlaceAndFill test place then immediately fill orders for multiple prices, meaning the matching loop will be somewhat busy. The PlaceBuyThenSell test place many buy orders, then place many sell orders, like an "all at once" operation. I'm still testing whether or not running matching for the price of an order immediately after the order is placed is a good idea, or any slower. The following only run the matching loop. The matching loop can be optimized as well, maybe it should be run on a time increment when the exchange isn't that busy, and run on an order increment when the exchange is busy. ``` - dan@dan-pc  ~/Documents/Projects/opencx/cxbenchmark   master  go test -v -benchtime=10s -bench=. + dan@dan-pc  ~/Documents/Projects/opencx/cxbenchmark   master  go test -v -benchtime=10s -bench=. goos: linux goarch: amd64 pkg: github.com/mit-dci/opencx/cxbenchmark diff --git a/cxbenchmark/matchingbenchmark_test.go b/cxbenchmark/matchingbenchmark_test.go index 4df9607..03b5049 100644 --- a/cxbenchmark/matchingbenchmark_test.go +++ b/cxbenchmark/matchingbenchmark_test.go @@ -8,7 +8,6 @@ import ( "github.com/mit-dci/opencx/logging" ) -// TODO: fix problems where you do something unexpected network-wise and the entire rpc server crashes! func BenchmarkPlaceOrders(b *testing.B) { var err error diff --git a/cxdb/cxdbsql/auctionqueries.go b/cxdb/cxdbsql/auctionqueries.go index 824f379..a885583 100644 --- a/cxdb/cxdbsql/auctionqueries.go +++ b/cxdb/cxdbsql/auctionqueries.go @@ -197,7 +197,63 @@ func (db *DB) NewAuction(auctionID [32]byte) (height uint64, err error) { return } -// MatchAuction matches the auction with a specific auctionID. This is meant to be the implementation of pro-rata for just the stuff in the auction. We assume that there are orders in the auction orderbook that are ALL valid. +/* + MatchAuction matches the auction with a specific auctionID. This is meant to be the implementation of pro-rata for just the stuff in the auction. We assume that there are orders in the auction orderbook that are ALL valid. + +To understand Pro-rata matching on a batch of orders, here is an example of an orderbook, where the "Buy" list represents all of the buy orders +and the "Sell" list represents all of the sell orders. + +The pair is BTC/LTC, you "buy" BTC with LTC and "sell" BTC for LTC. + + "Sell": [ + so1: { + amountWant: 300 LTC, + amountHave: 100 BTC, + // price : 0.33 + }, + so2: { + amountWant: 400 LTC, + amountHave: 100 BTC, + // price : 0.25 + }, + so3: { + amountWant: 600 LTC, + amountHave: 100 BTC, + // price : 0.17 + }, + so4: { + amountWant: 70 LTC, + amountHave: 10 BTC, + // price : 0.15 + }, + ] + "Buy": [ + bo1: { + amountWant: 100 BTC, + amountHave: 100 LTC, + // price : 1.00 + }, + bo2: { + amountWant: 100 BTC, + amountHave: 300 LTC, + // price : 0.33 + }, + bo3: { + amountWant: 100 BTC, + amountHave: 500 LTC, + // price : 0.20 + }, + bo4: { + amountWant: 10 BTC, + amountHave: 50 LTC, + // price : 0.20 + }, + ] + +We can see here that there's no "nice" way to match these orders, the high/low prices on either end are competitive, nor are there many orders +that are the same price. Pro-rata matching for a single price is trivial. + +*/ func (db *DB) MatchAuction(auctionID [32]byte) (height uint64, err error) { var tx *sql.Tx @@ -230,11 +286,6 @@ func (db *DB) MatchAuction(auctionID [32]byte) (height uint64, err error) { var book map[float64][]*match.AuctionOrder book = make(map[float64][]*match.AuctionOrder) - // I hate writing matching algorithms!!!!! - // Alright so here's what's going to happen: - // uh two lists? How does crossing work with pro rata - // very annoying, maybe it's time to look at other examples - for _, pair := range db.pairsArray { // So we get the orders, and they are supposed to be all valid. diff --git a/cxrpc/README.md b/cxrpc/README.md index f6eb723..dabb0a6 100644 --- a/cxrpc/README.md +++ b/cxrpc/README.md @@ -44,7 +44,7 @@ This will print a description of the order after making it, and prompt the user `ocx placeorder name {buy|sell} pair amountHave price` -The price is price, amountHave is the amount of the asset you have. If you're on the selling side, that will be the first asset1 in the asset1/asset2 pair. If you're on the buying side, that will be the second, asset2. +The price is price, amountHave is the amount of the asset you have. If you're on the selling side, that will be the first asset1 in the asset1/asset2 pair. If you're on the buying side, that will be the second, asset2. Arguments: - Name (string) diff --git a/cxrpc/bankcmds.go b/cxrpc/bankcmds.go index a45bb26..0b484c3 100644 --- a/cxrpc/bankcmds.go +++ b/cxrpc/bankcmds.go @@ -96,8 +96,6 @@ type WithdrawArgs struct { Signature []byte } -// TODO: figure out a good way to do this serialize and signature stuff!! - // WithdrawReply holds the reply for Withdraw type WithdrawReply struct { Txid string diff --git a/cxrpc/channelcmds.go b/cxrpc/channelcmds.go index 40903a3..01defd8 100644 --- a/cxrpc/channelcmds.go +++ b/cxrpc/channelcmds.go @@ -44,7 +44,6 @@ func (cl *OpencxRPC) GetLitConnection(args GetLitConnectionArgs, reply *GetLitCo return } - // TODO: figure out how to use the rest of the port list reply.Ports[i] = uint16(port64) } diff --git a/cxrpc/ordercmds.go b/cxrpc/ordercmds.go index 0e379b4..6ed7b67 100644 --- a/cxrpc/ordercmds.go +++ b/cxrpc/ordercmds.go @@ -42,7 +42,6 @@ func (cl *OpencxRPC) SubmitOrder(args SubmitOrderArgs, reply *SubmitOrderReply) return } - // TODO: make sure this is a valid way of doing stuff if !sigPubKey.IsEqual(orderPubkey) { err = fmt.Errorf("Pubkey used with signature not equal to the one passed") return @@ -156,7 +155,6 @@ func (cl *OpencxRPC) CancelOrder(args CancelOrderArgs, reply *CancelOrderReply) return } - // TODO: make sure this is a valid way of doing stuff if !sigPubKey.IsEqual(orderPubKey) { err = fmt.Errorf("Pubkey used with signature not equal to the one passed") return @@ -230,7 +228,6 @@ func (cl *OpencxRPC) GetOrder(args GetOrderArgs, reply *GetOrderReply) (err erro return } - // TODO: make sure this is a valid way of doing stuff if !sigPubKey.IsEqual(orderPubKey) { err = fmt.Errorf("Pubkey used with signature not equal to the one passed") return diff --git a/cxserver/keymgmt.go b/cxserver/keymgmt.go index 7b98230..c90ab12 100644 --- a/cxserver/keymgmt.go +++ b/cxserver/keymgmt.go @@ -6,7 +6,6 @@ import ( "github.com/mit-dci/lit/btcutil/base58" "github.com/mit-dci/lit/coinparam" "github.com/mit-dci/lit/crypto/koblitz" - "github.com/mit-dci/lit/wallit" ) // GetAddrForCoin gets an address based on a wallet and pubkey @@ -15,38 +14,17 @@ func (server *OpencxServer) GetAddrForCoin(coinType *coinparam.Params, pubkey *k if !found { err = fmt.Errorf("Could not find wallet to create address for") } - if addr, err = GetAddrFunction(wallet)(pubkey); err != nil { - return - } - - return -} - -// TODO: honestly just delete this at some point. If anyone wants a free pull request just -// make GetAddrFunction a function with 2 parameters. -// GetAddrFunction returns a function that can safely be called by the DB -func GetAddrFunction(wallet *wallit.Wallit) func(*koblitz.PublicKey) (string, error) { pubKeyHashAddrID := wallet.Param.PubKeyHashAddrID - return func(pubkey *koblitz.PublicKey) (addr string, err error) { - // TODO: in the future this should be deterministic based on public key. - // This is to make it really easy to figure out stuff - - defer func() { - if err != nil { - err = fmt.Errorf("Problem with address closure: \n%s", err) - } - }() - - // Create a new address - var addrBytes [20]byte - if addrBytes, err = wallet.NewAdr160(); err != nil { - return - } - - // encode it to store in own db - addr = base58.CheckEncode(addrBytes[:], pubKeyHashAddrID) + // Create a new address + var addrBytes [20]byte + if addrBytes, err = wallet.NewAdr160(); err != nil { return } + + // encode it to store in own db + addr = base58.CheckEncode(addrBytes[:], pubKeyHashAddrID) + + return } diff --git a/cxserver/lightning.go b/cxserver/lightning.go index 8e8e1e3..0e8bd54 100644 --- a/cxserver/lightning.go +++ b/cxserver/lightning.go @@ -328,8 +328,6 @@ func (server *OpencxServer) CreateSwap(pubkey *koblitz.PublicKey, order *match.L // } } - // TODO: once everything is revealed, - return } diff --git a/dextechsurvey.md b/dextechsurvey.md index b7712a2..a3a6332 100644 --- a/dextechsurvey.md +++ b/dextechsurvey.md @@ -12,7 +12,7 @@ It's good to get a survey of the research and not-yet-implemented solutions to p - [x] [dFusion](https://github.com/gnosis/dex-research/tree/master/dFusion) - [x] [Batch Auction Optimization](https://github.com/gnosis/dex-research/tree/master/BatchAuctionOptimization) - [x] [Plasma Research](https://github.com/gnosis/dex-research/tree/master/PlasmaResearch) - - [x] Vitalik Reddit: [Let's run on-chain decentralized exchanges the way we run prediction markets](https://www.reddit.com/r/ethereum/comments/55m04x/lets_run_onchain_decentralized_exchanges_the_way/) + - [x] Vitalik Reddit: [Let's run on-chain decentralized exchanges the way we run prediction markets](https://www.reddit.com/r/ethereum/comments/55m04x/lets_run_onchain_decentralized_exchanges_the_way/) - [x] ethresear.ch ["Decentralized exchanges" category](https://ethresear.ch/c/decentralized-exchanges) as of 2/19/2019 - [x] [Introducing DTRADE. Confoederation dapp](https://ethresear.ch/t/introducing-dtrade-confoederatio-dapp/4870) - [x] [Self-referential proxy exchange - does this exist?](https://ethresear.ch/t/self-referential-proxy-exchange-does-this-exist/4515) @@ -113,7 +113,7 @@ There's a note about unidirectional channels and how publishing the most recent Finally, there are a lot of diagrams about their implementation of limit orders and RFQs, and they also explain bidirectional RFQ's, where if you bought one asset then you should be able to also sell it back with another RFQ. It's a very dry paper but it's a very solid idea. It is still a market maker but as far as non custodial exchanges go, this is a good way to do it. -Also in the arwen paper there's a mistake, on the last page it says that "Plasma [28] is a proposal for a layer-two decentralized exchange protocol on Ethereum", which is false. Plasma is a proposal for layer-two off-chain transactions on ethereum, much like lightning but for ethereum. +Also in the arwen paper there's a mistake, on the last page it says that "Plasma [28] is a proposal for a layer-two decentralized exchange protocol on Ethereum", which is false. Plasma is a proposal for layer-two off-chain transactions on ethereum, much like lightning but for ethereum. ## Nash / NEX @@ -140,7 +140,7 @@ Here's a basic run-through of what would happen: This is one of the most thoughtful pieces of decentralized exchange research, since they fully recognize that the matching engine will have to be trusted, and count it as a trade-off. The efforts towards making the matching less centralized are also thoughtful. ### The Heart of Nash Article review and thoughts -This article is essentially a tip-of-the-iceberg explanation of the Nash matching engine, which claims to be a "provably fair, distributed system". This is the selling point of their decentralized exchange technology. They openly say that they are trading off trust in matching for the huge speed bonus you get by not having extremely redundant computation, like other DEXes that have their matching not off chain. They acknowledge this by requiring that their matching engine be provably fair and deterministic, so users can verify there is nothing bad happening. +This article is essentially a tip-of-the-iceberg explanation of the Nash matching engine, which claims to be a "provably fair, distributed system". This is the selling point of their decentralized exchange technology. They openly say that they are trading off trust in matching for the huge speed bonus you get by not having extremely redundant computation, like other DEXes that have their matching not off chain. They acknowledge this by requiring that their matching engine be provably fair and deterministic, so users can verify there is nothing bad happening. Their matching engine is a distributed system with its own consensus algorithm. @@ -181,7 +181,7 @@ Supposedly the point is that the users of the system are participating in a sort ### Batch auctions with uniform clearing price on plasma This is a post by one of the gnosis people trying to spur conversation about their papers on batch auctions for eliminating front-running and bundling liquidity. Here is the basic idea: -Consider the ethereum root / plasma chain model. The plasma chain is necessary for throughput as well as slashing conditions for collusion. The first step is that a set of "bonded" participants participate in distributed key generation. If they try to reveal secret messages that were exchanged in the distributed key generation process before the auction is over, they are subject to slashing. Then, those who would like to place orders will place them within a set period of time (the auction time), and once that time period is over the orders are revealed, price is calculated, and proofs for order settlement / matching are generated. +Consider the ethereum root / plasma chain model. The plasma chain is necessary for throughput as well as slashing conditions for collusion. The first step is that a set of "bonded" participants participate in distributed key generation. If they try to reveal secret messages that were exchanged in the distributed key generation process before the auction is over, they are subject to slashing. Then, those who would like to place orders will place them within a set period of time (the auction time), and once that time period is over the orders are revealed, price is calculated, and proofs for order settlement / matching are generated. This is another one of those things that seems only useful on ethereum and doesn't really have much to do with decentralized exchange, other than their $1200 snark-based order matching, which is also essentially their version of a proof of work but it's on ethereum so _slashing fixes everything_. @@ -199,7 +199,7 @@ This is just a complaint that DutchX isn't available in certain countries. Vitalik here addresses the issues of miners being able to front-run automated market maker based exchanges for profit. He proposes a way to turn that profit into the very least a griefing attack by the miner. ### Limit orders and slippage resistance in `x*y=k` market makers -The problem discussed in this post is basically that once you start taking up a large amount of the liquidity of the automated market maker, there's a high rate per token. The OP of this post is one of the two uniswap members, and he proposes a way to use on-chain limit orders as well as the automated `x*y=k` market maker to fill orders with high volume as well as those with low volume without too much "price slippage" due to trade volume increasing rate, in the nature of `x*y=k` market makers. +The problem discussed in this post is basically that once you start taking up a large amount of the liquidity of the automated market maker, there's a high rate per token. The OP of this post is one of the two uniswap members, and he proposes a way to use on-chain limit orders as well as the automated `x*y=k` market maker to fill orders with high volume as well as those with low volume without too much "price slippage" due to trade volume increasing rate, in the nature of `x*y=k` market makers. The limit orders are not necessarily executed very quickly but they are executed without affecting the issues of placing high volume trades on automated market makers. ### Reverse Parimutuel Options on Bitcoin @@ -214,14 +214,14 @@ Binance chain is basically bitshares with a different consensus algorithm. They # Topics ## "Provably fair" matching -Provably fair matching is mostly a topic brought up by NEX / Nash. The idea is to make sure that the matching is completely deterministic so that anyone on any computer can verify that each step is being done correctly. I'm not sure if anyone will verify it, or if anyone will be able to, considering the whole point of an off chain matching engine is to remove computing redundantly, but it's an interesting idea. +Provably fair matching is mostly a topic brought up by NEX / Nash. The idea is to make sure that the matching is completely deterministic so that anyone on any computer can verify that each step is being done correctly. I'm not sure if anyone will verify it, or if anyone will be able to, considering the whole point of an off chain matching engine is to remove computing redundantly, but it's an interesting idea. -The actual question of "fairness" seems like a topic that is up to interpretation. Many believe that the price-time priority matching algorithm is the only fair algorithm. I'm not sure whether this is the case. -With price-time priority, there are issues with front-running and race conditions. There would be similar issues with bitcoin transactions if it didn't use transaction fees as incentive for miners to pick up transactions. With large distributed networks it would be difficult to determine "true" order of transactions anyways, since there would be conflicting opinions on which came first depending on how the transaction were propagated. +The actual question of "fairness" seems like a topic that is up to interpretation. Many believe that the price-time priority matching algorithm is the only fair algorithm. I'm not sure whether this is the case. +With price-time priority, there are issues with front-running and race conditions. There would be similar issues with bitcoin transactions if it didn't use transaction fees as incentive for miners to pick up transactions. With large distributed networks it would be difficult to determine "true" order of transactions anyways, since there would be conflicting opinions on which came first depending on how the transaction were propagated. Maybe price-fee priority makes the problem of decentralized matching much simpler, by removing a constraint that was put there in order to enforce undefined "fairness" (time). -One other issue with "provable fairness" is the issue that if you were to submit a log of all inputs, the current state, and a program to allow the user to verify that the inputs and program lead to the current state, then the user would take an equal amount of time to verify that the computation happened correctly. This isn't exactly feasible for most, since if we were to do this for Google then it's not like we all have servers that match up to Google's. +One other issue with "provable fairness" is the issue that if you were to submit a log of all inputs, the current state, and a program to allow the user to verify that the inputs and program lead to the current state, then the user would take an equal amount of time to verify that the computation happened correctly. This isn't exactly feasible for most, since if we were to do this for Google then it's not like we all have servers that match up to Google's. Also this means if you did this for a program that doesn't stop, you essentially have to be running a clone of the system that the prover is running in order to keep up. So it would be better if we could verify that an exchange did some algorithm correctly in less time than it took the algorithm to run, hopefully constant or something with better asymptotic performance. @@ -255,8 +255,6 @@ Some, like Nash, choose to settle trades by having the matching engine simultane ## Cryptographic Securities Exchanges ## Deconstructing Decentralized Exchanges -TODO: summary of essay and general opinion - The essay starts out by defining the architecture of a decentralized exchange, however it doesn't get one thing completely right. They state, > A decentralized exchange application builds on top of a decentralized exchange protocol, and adds an on-chain or off-chain order book database and a graphic user interface (GUI) and/or APIs so that the information is easily accessible. @@ -321,8 +319,8 @@ They finally go through the various use cases for decentralized exchanges such a 6. Trust Level The trust level is something very relevant, and they highlight 3 main things that need to be trusted in order for a user to trust a protocol: -> 1. the decentralized exchange application creator and operator to perform activities such as hosting and publishing order books or performing order matching, -> 2. the underlying decentralized exchange protocol, including relevant smart contracts, and +> 1. the decentralized exchange application creator and operator to perform activities such as hosting and publishing order books or performing order matching, +> 2. the underlying decentralized exchange protocol, including relevant smart contracts, and > 3. the security, miners, and validators of the underlying distributed ledger. They highlight the various reasons why users would sacrifice trust or place more importance on one or more of these three, and conclude the essay. @@ -334,7 +332,7 @@ This also exposes the total liabilities of the exchange. The more proofs are mad Provisions proposes a zero knowledge proof based solution to proof of solvency. One issue with doing this is that multiple exchanges could possibly collude to create a valid proof of solvency. However, they provide an extension to provisions which is able to prove that one exchange is not sharing addresses with another exchange running Provisions by also providing the result of a deterministic function on the private key. This does reveal the number of addresses (or private keys) the exchange controls though. -There are three protocols in Provisions: +There are three protocols in Provisions: 1. Proof of assets 2. Proof of liabilities 3. Proof of solvency @@ -348,7 +346,7 @@ Cryptographic primitives in Provisions: 3. Non-interactive Zero-Knowledge Proofs (NIZKP) - The paper says that they can be adapted from basic sigma protocols (like schnorr proof of knowledge of discrete log). - Any alternative sigma protocol to NIZKP compilation is sufficient (so just fiat-shamir whatever sigma protocol with knowledge soundness). - - Easiest proof of discrete log for me is the fiat-shamir'ed schnorr: + - Easiest proof of discrete log for me is the fiat-shamir'ed schnorr: - `s = k - h(R,m)a <=> sG = kG - h(R,m)aG <=> sG = R - h(R,m)A` Assumptions in Provisions: @@ -444,7 +442,7 @@ They explain proof of stake, and compare it to proof of work, as justification w 18 pages in, they start to explain Delayed Proof of Work. dPoW does not use the Chain with the most work for all blocks. Komodo has a stake-weighted vote to elect 64 separate notary nodes who notarize blocks. The system requires notary nodes to generate a hash of a block hash on the Komodo network, the block height of that block on the Komodo network, and the letters "KMD". -This gets published to the Bitcoin blockchain (or any other with Proof of Work) using an `OP_RETURN`. +This gets published to the Bitcoin blockchain (or any other with Proof of Work) using an `OP_RETURN`. This hash will get concatenated with the txid on whatever chain it's published on, and then that will be submitted with a notarization transaction to the Komodo chain. Every 65 blocks, a notary node gets the chance to mine the Komodo chain on "easy mode" (which I think is 10 zeros at the beginning of a block). Each notary is on its own cycle, so for 64 blocks notary nodes will be the only miners. Non notary nodes can theoretically mine during this period but probably won't because easy mode is so easy. @@ -455,7 +453,7 @@ At least 13 notaries are required to post a notarization transaction on the main In Komodo, there are also asset chains, but the notary nodes only mine the main chain. Asset chains are notarized to the main KMD chain in the same way the KMD chain is notarized to a chain like bitcoin. -It also apparently costs money (about 180BTC or $1,500,000) to run all the notary nodes. There are fees and payments to notary nodes if you would like to create an asset chain. This is about 333 KMD and 333 of the asset coin. +It also apparently costs money (about 180BTC or $1,500,000) to run all the notary nodes. There are fees and payments to notary nodes if you would like to create an asset chain. This is about 333 KMD and 333 of the asset coin. Notary nodes make their profit from mining the KMD chain. ### The Decentralized Initial Coin Offering @@ -517,7 +515,7 @@ Then the smart contract verifies that the signature originated from the order ma IDEX uses smart contracts for settlement but stores balances, the orderbook, transaction queue, and matching engine on IDEX servers. The user deposits into a smart contract and places an order using that smart contract. The IDEX server is authenticated to execute signed orders on the smart contract, and when it matches orders it calls a smart contract method to settle two smart contracts. Balances are updated and users can withdraw if they'd like. ## Uniswap -Uniswap is an implementation of an `x*y=k` market maker, where there is some constant `k`, and `x` is an amount of one asset stored in the smart contract, and `y` is an amount of another asset stored in the smart contract. Suppose I created a `x*y=k` market maker, specified the constant to be `100`, and funded it with 10 BTC as `x` and 10 LTC as `y`. +Uniswap is an implementation of an `x*y=k` market maker, where there is some constant `k`, and `x` is an amount of one asset stored in the smart contract, and `y` is an amount of another asset stored in the smart contract. Suppose I created a `x*y=k` market maker, specified the constant to be `100`, and funded it with 10 BTC as `x` and 10 LTC as `y`. The price is 1 BTC/LTC. diff --git a/features.md b/features.md index a659455..f7f2223 100644 --- a/features.md +++ b/features.md @@ -27,63 +27,15 @@ Keeping the block header, I need something to check that it's not an orphan bloc Only once the current height and height stored in the DB differ by the # of confirmations stored along with the deposit, do we make a DB update on the balances table. -# Current features - - - [x] RPC Interface - - [x] DB Interface - - [x] Testnet interface - - [x] Wallets - - [x] Withdrawal - - [x] Test on testnet - debug transaction sending / pushing - - [x] Register - - [x] RPC Command in interface - - [x] Place order - - [x] Orders and trading pairs in DB - - [x] Different coins in DB - - [x] Account balances for said coins in DB - - [x] Get balance - - [x] Different coins in DB - - [x] Account balances for said coins in DB - - [x] View orderbook - - [x] Orders in DB - - [x] Get Address - - [x] Testnet interface - - [x] Deposit addresses in DB - - [x] Deposit - - [x] Testnet interface - - [x] Deposit confirmations variable - - [x] How to confirm deposit - - [x] Create master private key - - [x] Signing - - [x] Sign all messages to/from for identification - - [x] Matching engine - - [x] Get all balances - - [x] Extra command - - [x] Get Price - - [x] Remove token stuff in shell - - [x] ~~Correct dynamic confirmations~~ fixed but I just changed it to 6, but it *could* be made a lot better because I made it easy to do so. - - [x] **Get robust way of adding multiple tokens** - - [x] Fix issue with price calculation on sell side - - [ ] Fix SQL Injection - - [ ] Lightning Features - - [ ] Protocol for custodial only-on-orderbook exchange - - [ ] Lightning atomic swap - - [x] OpenCX code for off-chain HTLC-based atomic swaps and cross-chain channel management - - [ ] Lit code for HTLC-based atomic swaps - - [x] Lightning fund and push deposit - - [x] Lightning withdrawal - - [x] Lightning push back on withdrawal channel as deposit - - [ ] Magic: fully non custodial exchange without the free option problem - ## Note on phishing -If people were to tell other people "send me bitcoin and I'll credit you on my OpenCX exchange" that's ripe for phishing. +If people were to tell other people "send me bitcoin and I'll credit you on my OpenCX exchange" that's ripe for phishing. It's just a bitcoin/vertcoin/litecoin/lightning node, how do people know that's the service being provided? ## Note on proofs One thing I've been more and more interested in as a research topic has been the idea of a publicly auditable exchange. This means that things like Provisions will be produced. One possibility I've been exploring is the idea that liabilities are essentially proof of users for the exchange, and proof of assets (like in Provisions) backs those users up with money. The idea behind this is then the exchange might be able to then "prove" that an action occurred, and that action is backed up by some liabilities. -Provisions then proves that these liabilities are backed up by real assets. -An exchange can "create" fake liabilities, but those then need to be backed up by assets. +Provisions then proves that these liabilities are backed up by real assets. +An exchange can "create" fake liabilities, but those then need to be backe up by assets. So the proof of liabilities needs to be reused for both the provisions proof and any other proofs in order for this to work. This also might be a completely horrible way to do things. Provisions isn't perfect, you need to use P2PK, and it requires users to check their own accounts. It also isn't super efficient, but that might not be avoidable given number of users. Given the recent SEC report by Bitwise, even considering the fact that the entire thing might not be true at all (I doubt it but you never know), it's clear that wash trading is something that a malicious exchange could do. @@ -101,4 +53,4 @@ Figure out, maybe based on historical data, see how much the optionality in the ### Architecture notes I've realized that the wallet should probably be decoupled. As the exchange, we just rely on something that takes in transactions and tells us if we've received the money yet, so basically a wallet. We should be able to just connect to that thing, ask it about what addresses it has and has been sent to. -Key management has always been an issue but I'd like to just keep one thing synced up and connect to that, and lit is the most compatible with the chainhook and stuff. I'm sure I'm storing like 3 copies of everything. +Key management has always been an issue but I'd like to just keep one thing synced up and connect to that, and lit is the most compatible with the chainhook and stuff. I'm sure I'm storing like 3 copies of everything. diff --git a/go.mod b/go.mod index 98c50af..aa3a100 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/btcsuite/btcd v0.0.0-20190427004231-96897255fd17 // indirect github.com/btcsuite/fastsha256 v0.0.0-20160815193821-637e65642941 github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8 + github.com/btcsuite/goleveldb v1.0.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dchest/siphash v1.2.1 github.com/dgryski/go-rc5 v0.0.0-20181025211356-a14dd155920a @@ -17,7 +18,9 @@ require ( github.com/go-sql-driver/mysql v1.4.1 github.com/golang/protobuf v1.3.1 // indirect github.com/jessevdk/go-flags v1.4.1-0.20181221193153-c0795c8afcf4 + github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec // indirect github.com/kr/pretty v0.1.0 // indirect + github.com/kr/pty v1.1.4 // indirect github.com/mattn/go-isatty v0.0.7 // indirect github.com/mattn/go-runewidth v0.0.4 // indirect github.com/minio/highwayhash v1.0.0 @@ -30,7 +33,7 @@ require ( golang.org/x/net v0.0.0-20190520210107-018c4d40a106 // indirect golang.org/x/sys v0.0.0-20190520201301-c432e742b0af // indirect golang.org/x/text v0.3.2 // indirect - google.golang.org/appengine v1.6.0 // indirect + golang.org/x/tools v0.0.0-20190520220859-26647e34d3c0 // indirect gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/yaml.v2 v2.2.2 // indirect ) diff --git a/go.sum b/go.sum index 43ba046..6a69449 100644 --- a/go.sum +++ b/go.sum @@ -11,7 +11,6 @@ github.com/bitgoin/lyra2rev2 v0.0.0-20161212102046-bae9ad2043bb h1:2FbdV3Tfmli5z github.com/bitgoin/lyra2rev2 v0.0.0-20161212102046-bae9ad2043bb/go.mod h1:0vfuB+dfDvUoqr7oGBAZzGvaAyxfKFsYnRwUrNM4ft8= github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= -github.com/btcsuite/btcd v0.0.0-20190427004231-96897255fd17 h1:m0N5Vg5nP3zEz8TREZpwX3gt4Biw3/8fbIf4A3hO96g= github.com/btcsuite/btcd v0.0.0-20190427004231-96897255fd17/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= @@ -21,11 +20,12 @@ github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQz github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8 h1:nOsAWScwueMVk/VLm/dvQQD7DuanyvAUb6B3P3eT274= github.com/btcsuite/golangcrypto v0.0.0-20150304025918-53f62d9b43e8/go.mod h1:tYvUd8KLhm/oXvUeSEs2VlLghFjQt9+ZaF9ghH0JNjc= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/blake256 v1.0.0 h1:6gUgI5MHdz9g0TdrgKqXsoDX+Zjxmm1Sc6OsoGru50I= github.com/dchest/blake256 v1.0.0/go.mod h1:xXNWCE1jsAP8DAjP+rKw2MbeqLczjI3TRx2VK+9OEYY= @@ -41,7 +41,6 @@ github.com/ethereum/go-ethereum v1.8.27 h1:d+gkiLaBDk5fn3Pe/xNVaMrB/ozI+AUB2IlVB github.com/ethereum/go-ethereum v1.8.27/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/getlantern/deepcopy v0.0.0-20160317154340-7f45deb8130a h1:yU/FENpkHYISWsQrbr3pcZOBj0EuRjPzNc1+dTCLu44= github.com/getlantern/deepcopy v0.0.0-20160317154340-7f45deb8130a/go.mod h1:AEugkNu3BjBxyz958nJ5holD9PRjta6iprcoUauDbU4= @@ -50,32 +49,28 @@ github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8w github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c h1:kQWxfPIHVLbgLzphqk3QUflDy9QdksZR4ygR807bpy0= github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= -github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc= github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA= github.com/jackpal/go-nat-pmp v0.0.0-20181021122511-d89d09f6f332 h1:taVnlVCxVFm9YTGyVhvCXxFii5jzI2HRRWvJzRTg+LY= github.com/jackpal/go-nat-pmp v0.0.0-20181021122511-d89d09f6f332/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.1-0.20181221193153-c0795c8afcf4 h1:xKkUL6QBojwguhKKetf1SocCAKqc6W7S/mGm9xEGllo= github.com/jessevdk/go-flags v1.4.1-0.20181221193153-c0795c8afcf4/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/pty v1.1.4/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.6 h1:SrwhHcpV4nWrMGdNcC2kXpMfcBVYGDuTArqyhocJgvA= github.com/mattn/go-isatty v0.0.6/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= @@ -83,7 +78,6 @@ github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/ github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/minio/highwayhash v1.0.0 h1:iMSDhgUILCr0TNm8LWlSjF8N0ZIj2qbO8WHp6Q/J2BA= github.com/minio/highwayhash v1.0.0/go.mod h1:xQboMTeM9nY9v/LlAOxFctujiv5+Aq2hR5dxBpaMbdc= -github.com/mit-dci/lit v0.0.0-20190430192525-57c63ed5cc95 h1:LhHcPZcc/vHPboI+zuOyiJpyV2k4WG0s1bBH/ayr7m0= github.com/mit-dci/lit v0.0.0-20190430192525-57c63ed5cc95/go.mod h1:w4kLxTIH6bwnHCwyTzyrTBnRWBFej4EWyCP10AElz6g= github.com/mit-dci/zksigma v0.0.0-20190313133734-a6a19e83b9cc h1:PEL0ufWv+QReiQYnQbC5bSDlzhwa1G/yqr7DTD18MHA= github.com/mit-dci/zksigma v0.0.0-20190313133734-a6a19e83b9cc/go.mod h1:h5xTiloHHHbImqJ5T2797UliBzlsFWtBbOjuoRJ1yzM= @@ -91,10 +85,9 @@ github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8u github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/vertcoin/lyra2re v0.0.0-20170910033546-8bfa142041c2 h1:xf2HNsfB8pLNxjeWq3/LSPel2FiBhzF+ouaoquGPpvc= github.com/vertcoin/lyra2re v0.0.0-20170910033546-8bfa142041c2/go.mod h1:nzsIXJSsbS8epdXKijPDv2EmN40Vp0KzIwniHMnygHY= @@ -107,37 +100,31 @@ golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f h1:R423Cnkcp5JABoeemiGEPlt9tHXFfw5kvc0yqlxRPWo= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190301231341-16b79f2e4e95/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190520210107-018c4d40a106 h1:EZofHp/BzEf3j39/+7CX1JvH0WaPG+ikBrqAdAPf+GM= golang.org/x/net v0.0.0-20190520210107-018c4d40a106/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190306171555-70f529850638/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190520201301-c432e742b0af h1:NXfmMfXz6JqGfG3ikSxcz2N93j6DgScr19Oo2uwFu88= golang.org/x/sys v0.0.0-20190520201301-c432e742b0af/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -google.golang.org/appengine v1.6.0 h1:Tfd7cKwKbFRsI8RMAD3oqqw7JPFRrvFlOsfbgVkjOOw= -google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +golang.org/x/tools v0.0.0-20190520220859-26647e34d3c0/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/match/auctionorder_test.go b/match/auctionorder_test.go index d8a1bd4..e608b87 100644 --- a/match/auctionorder_test.go +++ b/match/auctionorder_test.go @@ -103,16 +103,20 @@ func solveVariableRC5AuctionOrder(howMany uint64, timeToSolve uint64, t *testing return } +// This should be super quick. Takes 0.1 seconds on an i7 8700k, most of the time is probably +// spent creating the test to solve. func TestConcurrentSolvesN10_T10000(t *testing.T) { solveVariableRC5AuctionOrder(uint64(10), uint64(10000), t) return } +// This should be less quick but still quick. Takes about 0.7 seconds on an i7 8700k func TestConcurrentSolvesN10_T100000(t *testing.T) { solveVariableRC5AuctionOrder(uint64(10), uint64(100000), t) return } +// TestConcurrentSolvesN10_T10000000 takes about 72 seconds on an i7 8700k func TestConcurrentSolvesN10_T10000000(t *testing.T) { solveVariableRC5AuctionOrder(uint64(10), uint64(10000000), t) return diff --git a/match/price.go b/match/price.go index 8520116..ebfb48b 100644 --- a/match/price.go +++ b/match/price.go @@ -5,7 +5,9 @@ import ( "math/big" ) -// Price represents an exchange rate. It's basically a fancy fraction. It follows the Want / Have method of doing things. Removal of Want/Have is TODO. +// Price represents an exchange rate. It's basically a fancy fraction. It follows the Want / Have method of doing things. +// TODO: The price and side can be represented as a single struct that contains the Asset the user wants (AssetWant), the Asset that the user has (AssetHave), the amount of AssetHave the user is willing to give up, and the amount of AssetWant that the user would like. +// This way there is no reason to have a "side" field, and prices can be represented more fairly, where you do not need to worry about precision other than the maximum precision of the asset, which is usually within a uint64. // We don't want this to be a big int because that means it can't really be sent over the wire. We're not multiple precision here, but we do want some // standard, reasonable level of precision type Price struct {