Giter Site home page Giter Site logo

exchangeunion / xud Goto Github PK

View Code? Open in Web Editor NEW
115.0 17.0 49.0 10.04 MB

Exchange Union Daemon ๐Ÿ” โšก๏ธ

Home Page: https://exchangeunion.com

License: GNU Affero General Public License v3.0

JavaScript 1.12% TypeScript 87.12% Shell 0.28% PowerShell 0.02% Go 11.30% Dockerfile 0.16%
lightning bitcoin dex ethereum xud connext opendex

xud's Introduction

Exchange Union Daemon

Discord CI Status SimTest Status Codacy Badge License: AGPL v3

xud logo

The Exchange Union Daemon (xud) is the reference implementation powering OpenDEX, a decentralized exchange built on top of the Lightning and Connext networks. xud brings individual traders, market makers and exchanges onto OpenDEX to form a single global trading network and liquidity pool.

Get started ๐Ÿ‘‰ here ๐Ÿ‘ˆ

OpenDEX Network Specification Compliance

xud implements the OpenDEX protocol and fully conforms to its so-called BOLD specifications. BOLD stands for: Basis of L3 DEX. The naming is intentionally derived from BOLT, the Lightning Network specifications and role model of OpenDEX. The specifications are currently being drafted by several implementers based around the world, including the developers of xud. The BOLDs, as well as xuds implementation of it is still a work-in-progress. The current status of xud's BOLD compliance is:

xud encompasses the following components:

  • Integration with lnd and connext clients.
  • Decentralized order book to locally aggregate orders from the known network.
  • Matching engine to match new local orders with existing local and remote orders and initiate atomic swaps with remote peers.
  • Peer-to-peer networking with and discovery of other nodes.
  • gRPC API with web proxy to serve other applications, also accessible via the command-line interface xucli.

Documentation

The daemon has been designed to be as developer friendly as possible in order to facilitate application development on top of xud.

Installation

This section contains brief instructions for installing xud manually, without treating setup of dependencies like bitcoind or lnd. It is mainly geared towards developers. For all other users, we recommend our streamlined xud-docker setup.

If you already have Node.js installed, you can install xud via npm by running

sudo npm install xud -g --unsafe-perm

We officially support the current Node.js LTS only, since it often takes time for the latest version to be supported by the gRPC library. Detailed instructions for installing xud can be found in the installation & developer docs.

Usage

Launch xud:

./xud
2018-9-11 01:11:59 [GLOBAL] info: config loaded
2018-9-11 01:11:59 [GLOBAL] info: Local nodePubKey is 029a96c975d301c1c8787fcb4647b5be65a3b8d8a70153ff72e3eac73759e5e345
2018-9-11 01:11:59 [DB] info: connected to database. host:localhost port:3306 database:xud
2018-9-11 01:11:59 [P2P] info: p2p server listening on 0.0.0.0:8885
2018-9-11 01:11:59 [RPC] info: gRPC server listening on localhost:8886

Open a new terminal and issue commands to xud with the xucli command line tool. To see a list of available commands, run:

./xucli --help

You can find more information on how to use & configure xud in the docs for developers.

Note: If you installed xud globally via npm, you can run xud and xucli from anywhere. Otherwise you must run them from the bin folder.

License

All files in this repository are licensed under the GNU Affero General Public License v3.0 unless explicitly stated otherwise in the header of a given file.

Discussion

Comments, questions, and any development-related discussions are welcome in our Discord chat!

xud's People

Contributors

dependabot[bot] avatar engwarrior avatar erkarl avatar hatmer avatar immanuelsegol avatar itsbalamurali avatar kilrau avatar krrprr avatar lepremierhomme avatar michael1011 avatar moshababo avatar offerm avatar programarivm avatar raladev avatar reliveyy avatar robertsdotpm avatar rsercano avatar sangaman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xud's Issues

webproxy sanity tests

Add simple sanity integration tests for the webproxy.
Just need to check that on the appropriate configuration (webproxy.disable = false), the HTTP server is alive and responding (can simply ping one GET call).

Tests for a streaming call will be added later, after it will be supported. (#128, #137)

gulp inter-process communication problems

After discovering too many problems with using gulp through our tests, due to inter-process communication, I think we should get rid of this approach and create a base layer of task functions that can be consumed directly. gulp should still wrap it in order to create an easy tasks CLI.

TODO:

  • change our tasks to a plain JS functions, instead of gulp tasks
  • update our integration tests to consume them directly, and not through gulp-runner
  • update our gulpfile to expose them through the gulp CLI (as now)

Add database arg

When running ~/xud/bin $ ./xud symlink, rpc.port and p2p.port args are supported, to be able to override the global config. This is useful when trying to run a few xud instances on one machine.
In addition to these, a database arg need to be added, so that each instance can target a different database.

Add streaming gRPC call to listen to orderbook events

This issue is about notifying clients when order book events occur such as an ownOrder being filled.

Events:

  1. ownOrder added success/error (placeOrder)
  2. ownOrder removed success/error (cancelOrder)
  3. ownOrder removed (due to internal match)
  4. ownOrder removed (due to a successful swap that was instantiated remotely)
  5. peerOrder added
  6. peerOrder removed (due to non-internal match and successful swap)
  7. peerOrder removed (due to peer order invalidation)
  8. peerOrder removed (due to swap failure)

placeOrder response covers (1), (3), and (6) (handled by #479)
placeOrderSync sync response covers (4), (8) (handled by #479)
cancelOrder response covers (2)
subscribeOrders covers (4), (5), (7), and (8)

placeOrder, is asynchronous and just returns an immediate success/error of placing an order. Swap results come in via subscribeOrders. There is a second placeOrderSync call which returns fail/success of a swap where we inform the client synchronously if the swap actually was successful or failed.

Note:
We already have (1) , (2), and (3) taken care of.

Generate and use TLS certificates for gRPC layer

Currently, our gRPC layer is not using a TLS certificate. We'll need to generate one as part of our initialization process if none exists, and use it for all rpc calls similar to how we use the lnd cert for calls in LndService.ts.

gRPC

We want to switch our RPC layer to use gRPC.

At first, our current RPC server need to be migrated, together with XUClient which consumes it.

Second, the new gRPC server need to become web-compatible, to support browser clients. To do so, grpcwebproxy or a similar like solution need to be integrated, in a way that it's activation will be configurable. To test it, a new separated web client repo need to be created.

Establishing connection to offline peer results in error

After connecting to a peer, restarting xud while the peer is offline results in an error during the attempt to reestablish a connection during startup. We should handle and silently ignore peer connection errors (or maybe log with verbose) during startup, since it is expected that we won't necessarily be able to reconnect with all known peers.

(node:18872) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: connect ECONNREFUSED 127.0.0.1:9995
(node:18872) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
2018-6-9 11:52:10 [P2P] debug: Socket Error (localhost:9995): "Socket hangup"
2018-6-9 11:52:10 [P2P] error: peer error undefined

Unit tests: MatchingEngine

Should add unit tests for MatchingEngine class, for the following static methods:

  • getMatchingQuantity (some old tests which don't cover partial quantities scenarios already exists)
  • splitOrderByQuantity
  • match

Create database

When authenticating through sequelize to the database server by specifying a specific database which does not exists, an exception is thrown.

A possible solution would be to try to connect by specifying a specific database anyway, and if exception is thrown, reconnect without specifying one. Create the database with a raw query, and then either reconnect to the server or just define a new database context (should work in theory).

Other solution would be to always connect without specifying a specific database, create it if it does not exists, and then define the database context. If the database context trick doesn't work, and reconnecting is needed, then it's not a good solution.

Order Encryption (Mode 2, requires black/white-list to be implemented)

XUD's Order Signing

XUD enables two modes for signing an order:

  1. Sign order to verify authenticity of public key
  2. Sign & encrypt order to verify authenticity and enforce white-list

Mode 1 is the default and signs all orders with the XUD's private key. This ensures that the XUD_ID carried in the order's invoice is the actual ID of the XUD sending the invoice. We decided to place the XUD_ID directly in the invoice description field for a faster processing, since this avoids a payment hash vs. XUD_ID lookup for each incoming new order. This mode prevents XUD's pretending to be someone else and knowing the actual issuer of an order is important for the incentive & punishing mechanism to work. This mode connects to all available peers and is suitable for exchanges located in jurisdictions without a strict legal framework for digital assets.

Mode 2 is optional and additionally to everything Mode 1 does, XUD encrypts orders with the public key of each white-listed peer. This mode is more resource intensive and requires maintaining a white-list of peers. It is suitable for exchanges located in jurisdictions with a strict legal framework and ensures that order information can only be received and viewed by white-listed trading partners, e.g. other licensed exchanges.

This issue is about implementing Mode 2.

Add disconnect API method

Right now we can issue xud a command to connect to a peer, but we can't manually disconnect yet. We should add a disconnect API method via gRPC with xucli integration to allow for disconnecting from specific peers.

P2P auto connect

On every xud launch, automatically connect to all peer's enlisted on peers table.

xud init error: tls.cert file

After installing repo dependencies and running a MySQL instance (+ creating an xud database),
I receive the following error:

$ ./xud
2018-4-16 13:53:43 info: config loaded
2018-4-16 13:53:43 error: Error: ENOENT: no such file or directory, open '/Users/Chikel/Library/Application Support/Lnd/tls.cert'
at Object.fs.openSync (fs.js:646:18)
at Object.fs.readFileSync (fs.js:551:33)
at new LndClient (/Users/Chikel/sandbox/xud/lib/lndclient/LndClient.js:18:24)
at Xud.start (/Users/Chikel/sandbox/xud/lib/Xud.js:35:26)
at
at process._tickCallback (internal/process/next_tick.js:188:7)
at Function.Module.runMain (module.js:686:11)
at startup (bootstrap_node.js:187:16)
at bootstrap_node.js:608:3

Thanks!

Logger contexts

New Logger contexts are to be define, in addition to GLOBAL: DB, RPC, P2P, ORDERBOOK, LND, RAIDEN.
They should all have a static instance defined on Logger class, that should be used by the appropriate components, instead of Logger.global.
They should all map to the same output file for now, same as GLOBAL (xud.log), but should have a unique output format : [CONTEXT] ...

TypeScript POC

We want to asses switching over the project to TypeScript (TS).
To begin with, we need to set up the TS build automation, making sure the project remains debuggable in IDEs, and to provide a few examples of converting files code to the appropriate TS equivalent.

root imports

root imports ( import * from "lib/...") should be configured in TS and be used in files instead of stepping up the folders structure from the file's relative position.

Fix gRPC REST Web Proxy

We have defined a REST service in our xudrpc.proto file with the aim of using it to spin up an HTTP REST service with express. Currently, our implementation using the grpc-dynamic-gateway package is throwing errors, described briefly in #103. We should either fix the existing implementation or, preferably, implement a different approach of either writing our own dynamic REST gateway module in typescript for use in this project, or generating a REST server statically using grpc-gateway.

Swagger API Docs for Web API Proxy

The idea is to generate Swagger REST API documentation for web API proxy from the proto file.
This would involve.

  • Generation of swagger json file from protoc via protoc-gen-swagger
    Example: protoc DEFINITION.proto --swagger_out=logtostderr=true:.
  • Attach Swagger Docs Middleware to webproxy / express for serving the documentation.

DB connection error inspection

At the moment we inspect any Sequelize.ConnectionError as if it indicates that the database doesn't exists, although that error type is thrown on other scenarios as well.

A better inspection to the thrown error object should be made.

Make gRPC and web proxy listening host configurable

Right now, the gRPC service is hardcoded to listen only on localhost. We should make this configurable, leaving localhost as the default, to allow for rpc calls to potentially be made from a remote machine.

Add removeOrder API method

We should add methods to allow for removing of orders from the XUD orderbook. This is necessary in the case of a user canceling their order or an order being filled internally. This should have a call through the gRPC layer as well as xucli integration.

Fresh install - problem with lndrpc.proto

Installed xud for the first time. Tried to follow the instructions on https://github.com/ExchangeUnion/xud:

Started xud from bin directory without a config file resulted with:

2018-5-19 20:53:30 error: TypeError: Cannot read property 'ns' of null
at Object.load (/home/offerm/github/xud/node_modules/grpc/index.js:146:29)
at new LndClient (/home/offerm/github/xud/dist/lib/lndclient/LndClient.js:31:52)
at Xud. (/home/offerm/github/xud/dist/lib/Xud.js:49:34)
at Generator.next ()
at fulfilled (/home/offerm/github/xud/dist/lib/Xud.js:4:58)
at

Had to create a config file and change

rpcprotopath = "lndrpc.proto"

to

rpcprotopath = "../lndrpc.proto"

P2P Network Simulation

We need to set up an infrastructure for being able to deploy and monitor XUD in a full P2P network mode, on designated servers. There aren't many existing tools for this, and in case none of them is a viable option, we should use some free load testing tool like JMeter, and abuse to match our needs.

P2P Bootstraping

We need to fully define and our peer discovery methods, which are the most appropriate for our kind of P2P network and application, and the fallback hierarchy.

Ideas can be taken from libp2p and bitcoind.

Redesign P2P layer

Make P2P layer more OOP fashioned, centered around Pool and Peer objects.
Peer object should encapsulate all P2P communications, including all pre-defined packet types. It should self-contain all communications states (necessary for the handshaking procedure).

Verify connection to lnd

There's currently a TODO in the code to verify communication with lnd via grpc. This can be done with a simple getinfo call to lnd or establishing a stream to listen to invoice payments, for example.

Auto-restart support

When running multiple xud instances on one machine, it's necessary to do so with ~/xud/bin $ ./xud symlink, so that the distinguishing args can be used (rpc.port, p2p.port) for the different instances. When trying to run nodemon on it, it does not detect file changes.

xucli placeorder error

i just run ./xucli placeorder --price 0.12 --quantity 5
{ message: 'Cannot read property 'addInvoice' of undefined',
code: -32000 }

the server error stack trace is:
RPC server request: {"jsonrpc":"2.0","params":{"order":{"price":0.12,"quantity":5}},"method":"placeOrder","id":1}
2018-4-17 03:17:05 error: RPC server request (1) error TypeError: Cannot read property 'addInvoice' of undefined
at RpcMethods.placeOrder (/home/sky/xud/lib/rpcserver/RpcMethods.js:63:42)
at RpcServer.processRequest (/home/sky/xud/node_modules/http-jsonrpc-server/lib/http-jsonrpc-server.js:169:77)
at IncomingMessage.req.on.on (/home/sky/xud/node_modules/http-jsonrpc-server/lib/reqhandler.js:107:12)
at IncomingMessage.emit (events.js:180:13)
at endReadableNT (_stream_readable.js:1106:12)
at process._tickCallback (internal/process/next_tick.js:114:19)

how to solve it ?

db password of sample config causing errors

When using the sample config of the readme xud fails to start because of this error:

(node:27008) UnhandledPromiseRejectionWarning: Error: Parsing error on line 3, column 12: Expected "'", "'''", "+", "-", "[", "\"", "\"\"\"", "_", "false", "true", "{", [ \t] or [0-9] but "n" found.
    at Config.<anonymous> (/home/michael/Git/JavaScript/xud/dist/lib/Config.js:88:27)
    at Generator.next (<anonymous>)
    at /home/michael/Git/JavaScript/xud/dist/lib/Config.js:7:71
    at new Promise (<anonymous>)
    at __awaiter (/home/michael/Git/JavaScript/xud/dist/lib/Config.js:3:12)
    at Config.load (/home/michael/Git/JavaScript/xud/dist/lib/Config.js:76:16)
    at Xud.<anonymous> (/home/michael/Git/JavaScript/xud/dist/lib/Xud.js:42:31)
    at Generator.next (<anonymous>)
    at /home/michael/Git/JavaScript/xud/dist/lib/Xud.js:7:71
    at new Promise (<anonymous>)
    at __awaiter (/home/michael/Git/JavaScript/xud/dist/lib/Xud.js:3:12)
    at Xud.start (/home/michael/Git/JavaScript/xud/dist/lib/Xud.js:41:16)
    at Object.<anonymous> (/home/michael/Git/JavaScript/xud/bin/xud:95:5)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Function.Module.runMain (module.js:693:10)
    at startup (bootstrap_node.js:191:16)
    at bootstrap_node.js:612:3
(node:27008) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 3)
(node:27008) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

My config:

[db]
username="xud"
password = null
databse = "xud"
port = 3306
host = "localhost"

It is working fine when password = null is replaced with password = "". Could some add this to a pr? Creating a new one for a single line is kinda overkill.

I am using Ubuntu 18.04, MariaDB 10.1.29 and Node 8.11.2.

Use caching layer for db queries

One of our key performance improvements will be to use an in-memory caching layer such as redis for database queries. This issue tracks incorporating a caching solution, implementing it for existing db queries, and paving the way for caching to be used for queries to be added in the future.

gRPC streaming call example

Add a gRPC streaming call example, including the listener side: XUClient + the CLI layer. It should ideally hang the process and log the streaming to terminal.

RpcMethods.js getOrders() needs params

https://github.com/ExchangeUnion/xud/blob/master/lib/rpc/RpcMethods.js

getOrders()

An exchange will only be interested in this method to display some orders in their order book UI. Thus they probably only want to get the best 10 buy and sell orders. I think we need a parameter like an integer for the number of buy and sells (ordered by best price from top to bottom starting with the furthest sell, to the best sell, then starting with the best buy to the furthest buy). 0 returns all.

TS & nodemon

When running npm run dev, nodemon should start watching only TypeScript compilation is done.

Docker Containers

We need to set up a configurable docker container automation for all XUD service dependencies, in order to get a functioning dev environment without much hassle.

To begin with, we need to it for the database dependency (MySQL).

Later, we'll want to add all other dependencies:

  • LND
  • Raiden
  • Different blockchains clients

In addition, we might want to set up a container solution which includes XUD itself, for easy deployment in tests and in production.

Improve getInfo API method

We have a getInfo method that is currently very basic - it simply calls the underlying lnd getInfo method and passes this along. We should expand this call to provide more meaningful data about the state of an xud instance. Some ideas:

  • Number of peers connected
  • Number of trading pairs/currencies supported
  • Number of peer orders and own orders.
  • Info about the Raiden node.

Orderbook persistence

OrderBook.AddOwnOrder is matching new incoming orders on MatchingEngine, which holds a cache of the database orders in priority queues. When a match occurs, orders are removed from the cache, so we need to remove them from the database too, according to MatchingResult. Because that partial matching is supported, we should only update the order quantity, so that an order which has been entirely removed should have a quantity set to 0. In addition, we need to make sure we don't query 0 quantity orders (in the init stage). It should be considered as a soft delete.

P2P Handshake

After a connection is established between two peers, we will need to conduct an application-level handshake, to pass necessary information between the two sides, prior to all other communications.

The only information I thought as necessary already at this point, is the peer's P2P server port. The reason is that whilst each peer is listening on a configurable port, it connects as a client through a random port. This means that if the target peer will enlist the incoming-connection peer according to that port, it will be futile since that port cannot be used to reconnect back. This lead to situation where incoming connections won't be usable for future P2P bootstraping.

Besides that, I can think on other information which will be necessary to handshake on:

  • xud version
  • supported currency pairs
  • public key (it's also possible to simply attach it to the order packet, but it might be necessary to get that information beforehand for different reasons)

The handshake procedure should be flexible, so that new steps could be easily added later. It should block all other communications until it completes successfully.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.