Code Monkey home page Code Monkey logo

txbits / txbits Goto Github PK

View Code? Open in Web Editor NEW
187.0 49.0 168.0 5.07 MB

DISCLAIMER: TxBits is not affiliated with any active exchanges. Use them at your own risk and beware of any that violate the AGPL license terms by not releasing their source code as required.

Home Page: https://txbits.org

License: GNU Affero General Public License v3.0

Shell 0.49% HTML 18.79% Java 0.77% Scala 47.23% PLpgSQL 14.84% CSS 1.36% JavaScript 12.03% Ruby 4.48%

txbits's Introduction

TxBits

Build Status

An open source Bitcoin and crypto currency exchange

https://www.txbits.org

Dev environment setup TL;DR

  1. Get jdk-8
  2. Get postgres 9.3+ running on localhost with database name txbits_testnet, superuser user and password password
  3. Run ./txbits.sh run
  4. Log in at http://localhost:9000 as [email protected] with password qwerty123
  5. To run unit tests, create a database named txbits_test and run ./txbits.sh test
  6. Read the wiki pages https://github.com/txbits/txbits/wiki

License

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License along with this program. If not, see http://www.gnu.org/licenses/.


Copyright (C) 2014-2015 Viktor Stanchev & Kirk Zathey

txbits's People

Contributors

expert-soft avatar vikstrous avatar williambanks avatar zathey 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  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

txbits's Issues

Exception handling of invalid PGP keys

Entering an invalid PGP key on signup or the settings page results in an uncaught exception.

[error] p.c.s.n.PlayDefaultUpstreamHandler - Cannot invoke the action
org.bouncycastle.util.encoders.DecoderException: unable to decode base64 data: invalid characters encountered at end of base64 data

Make 2FA errors consistent

Entering no PIN, e.g. "", gives:

Two factor auth not configured.

Entering a string, e.g. "a", gives:

Server Error: Execution exception[[NumberFormatException: For input string: "a"]]

Entering an invalid PIN, e.g. "0", gives:

Invalid token.

All of them should give Invalid token. on the PIN entry page.

add client side check for password constaints

We don't accept passwords under 12 characters, but it seems like people attempt to use them often. We should let them know that their password won't be accepted using a client side check before they submit it and find out that it's too short.

Login action throws an error at prod

2016-07-16 06:51:26,027 - [ERROR] - from application in application-akka.actor.default-dispatcher-27 
Unable to log user in. An exception was thrown
java.lang.NoClassDefFoundError: Could not initialize class globals.package$
    at controllers.ProviderController$$anonfun$loginPost$1$$anonfun$apply$4.apply(ProviderController.scala:96) ~[txbits.txbits-1.0-SNAPSHOT-sans-externalized.jar:na]
    at controllers.ProviderController$$anonfun$loginPost$1$$anonfun$apply$4.apply(ProviderController.scala:91) ~[txbits.txbits-1.0-SNAPSHOT-sans-externalized.jar:na]
    at play.api.data.Form.fold(Form.scala:139) ~[com.typesafe.play.play_2.11-2.4.2.jar:2.4.2]
    at controllers.ProviderController$$anonfun$loginPost$1.apply(ProviderController.scala:89) [txbits.txbits-1.0-SNAPSHOT-sans-externalized.jar:na]
    at controllers.ProviderController$$anonfun$loginPost$1.apply(ProviderController.scala:86) [txbits.txbits-1.0-SNAPSHOT-sans-externalized.jar:na]
    at play.api.mvc.ActionBuilder$$anonfun$apply$16.apply(Action.scala:408) [com.typesafe.play.play_2.11-2.4.2.jar:2.4.2]
    at play.api.mvc.ActionBuilder$$anonfun$apply$16.apply(Action.scala:407) [com.typesafe.play.play_2.11-2.4.2.jar:2.4.2]
    at play.api.mvc.Action$.invokeBlock(Action.scala:533) [com.typesafe.play.play_2.11-2.4.2.jar:2.4.2]
    at play.api.mvc.Action$.invokeBlock(Action.scala:530) [com.typesafe.play.play_2.11-2.4.2.jar:2.4.2]
    at play.api.mvc.ActionBuilder$$anon$1.apply(Action.scala:493) [com.typesafe.play.play_2.11-2.4.2.jar:2.4.2]
    at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:105) [com.typesafe.play.play_2.11-2.4.2.jar:2.4.2]
    at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4$$anonfun$apply$5.apply(Action.scala:105) [com.typesafe.play.play_2.11-2.4.2.jar:2.4.2]
    at play.utils.Threads$.withContextClassLoader(Threads.scala:21) [com.typesafe.play.play_2.11-2.4.2.jar:2.4.2]
    at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:104) [com.typesafe.play.play_2.11-2.4.2.jar:2.4.2]
    at play.api.mvc.Action$$anonfun$apply$1$$anonfun$apply$4.apply(Action.scala:103) [com.typesafe.play.play_2.11-2.4.2.jar:2.4.2]
    at scala.Option.map(Option.scala:146) [org.scala-lang.scala-library-2.11.7.jar:na]
    at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:103) [com.typesafe.play.play_2.11-2.4.2.jar:2.4.2]
    at play.api.mvc.Action$$anonfun$apply$1.apply(Action.scala:96) [com.typesafe.play.play_2.11-2.4.2.jar:2.4.2]
    at play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:524) [com.typesafe.play.play-iteratees_2.11-2.4.2.jar:2.4.2]
    at play.api.libs.iteratee.Iteratee$$anonfun$mapM$1.apply(Iteratee.scala:524) [com.typesafe.play.play-iteratees_2.11-2.4.2.jar:2.4.2]
    at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:560) [com.typesafe.play.play-iteratees_2.11-2.4.2.jar:2.4.2]
    at play.api.libs.iteratee.Iteratee$$anonfun$flatMapM$1.apply(Iteratee.scala:560) [com.typesafe.play.play-iteratees_2.11-2.4.2.jar:2.4.2]
    at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$14.apply(Iteratee.scala:537) [com.typesafe.play.play-iteratees_2.11-2.4.2.jar:2.4.2]
    at play.api.libs.iteratee.Iteratee$$anonfun$flatMap$1$$anonfun$apply$14.apply(Iteratee.scala:537) [com.typesafe.play.play-iteratees_2.11-2.4.2.jar:2.4.2]
    at scala.concurrent.impl.Future$PromiseCompletingRunnable.liftedTree1$1(Future.scala:24) [org.scala-lang.scala-library-2.11.7.jar:na]
    at scala.concurrent.impl.Future$PromiseCompletingRunnable.run(Future.scala:24) [org.scala-lang.scala-library-2.11.7.jar:na]
    at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:40) [com.typesafe.akka.akka-actor_2.11-2.3.11.jar:na]
    at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:397) [com.typesafe.akka.akka-actor_2.11-2.3.11.jar:na]
    at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) [org.scala-lang.scala-library-2.11.7.jar:na]
    at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) [org.scala-lang.scala-library-2.11.7.jar:na]
    at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) [org.scala-lang.scala-library-2.11.7.jar:na]
    at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) [org.scala-lang.scala-library-2.11.7.jar:na]

lock down the database

We need the frontend server to have very limited permissions on the database. We can improve security significantly that way.

  • Use a separate user for the frontend and for the wallet
  • Use randomized user ids to minimize exposure in case of a frontend breach
  • Make sure that regular user functions don't work on user 0
  • Remove find_user_by_email
  • Authenticate password changes in postgres
  • Send password resets from the wallet instead of the frontend
  • Don't allow access to the free money api in prod

Log access in database functions

Instead of relying on the frontend to create a log of an access such as user authentication, the database function itself should create the log message. Something to keep in mind is that the function must commit successfully, possibly returning false or an unauthorized state, as if it throws an exception and rolls back, then the log message will not get written either.

Retrieve bids and asks in one query

I had written this in the code review for #29 but it makes more sense to have a separate issue.

I think we need to return the bids and asks in a single select query or the order books could appear inconsistent. For example, if we retrieve the bids first and then a sell order for less than the highest bid is committed before we query the asks, we could see an ask lower than the highest bid as well as bids that were already matched by this ask. This does not affect our database but it would look wrong to users and possibly affect automated trading bots. I suggest we use a function like this to get the order books atomically:

CREATE AGGREGATE array_agg_mult (anyarray) (
    SFUNC     = array_cat
   ,STYPE     = anyarray
   ,INITCOND  = '{}'
);

create function 
  orders_depth(
    a_base varchar(4),
    a_counter varchar(4),
    out asks numeric(23,8)[],
    out bids numeric(23,8)[])
  as $$
    select (
      select array_agg_mult(array[array[price, amount]]) from open_asks(a_base, a_counter)
    ), (
      select array_agg_mult(array[array[price, amount]]) from open_bids(a_base, a_counter)
    );
$$ language sql stable cost 100;

make function definitions more readable

We can put these things:

    LANGUAGE plpgsql SECURITY DEFINER
    SET search_path TO public, pg_temp

before the function body. We should do that eventually to make the function definitions cleaner.

think about tracking unassociated sends (withdraws) somehow

There is one case that leads to somewhat confusing results. When the exchange is running and we manually send money from an unassociated address to another unassociated address on the same wallet, it creates a send and a receive in bitcoind, but the exchange pickes up only the receive and thinks "hey, free money, let's give it to user 0", but it doesn't know that the money came from user 0 to begin with. Unassociated sends transactions are not reflected in the database AFAIK.

Fix login CSRF

It's not a big deal right now as we are still testing, but we should remember to add CSRF protection on the login form.

Wallet actor can get an incorrect balance

The wallet actor uses getbalance from bitcoind to determine if the wallet has enough funds to process withdrawals and if a transfer should be made to cold storage. Balance could be inaccurate from double spends or transaction malleability. This was fixed in Bitcoin in the following pull request: bitcoin/bitcoin#3671 Bitcoin and Litecoin are safe but altcoins may not have this patch and would need to be patched or the wallet actor needs to be modified to not get the balance from the daemon.

Great project

Will you able to change the AGPL to MIT License?
I think it will be more lovely project to work on and put it into production stage.

add some password advice

We should advise users to generate passwords with a password manager or make up random passwords and then write them down.

Restrict CSP further

Our current content security policy is:

default-src 'self' data: https://www.google-analytics.com https://*.uservoice.com; script-src 'self' 'unsafe-eval' https://www.google-analytics.com https://*.uservoice.com; style-src 'self' data: 'unsafe-inline'; font-src 'self' data:

(The development CSP is slightly different because Google Analytics and User Voice load over http when the page is served over http.)

Our CSP is limited by:

  • handlebars that uses dynamically constructed functions
  • uservoice that uses inline styles
  • uservoice that uses data: urls for a lot of things
  • google analytics and uservoice that require loading of external javascript
  • google analytics and uservoice that require data: urls

We should consider tightening the CSP by not using Google Analytics, User Voice and Handlebars or finding secure workarounds to use them with a stricter CSP.

deduplicate sql for authenticating uid/api key/other future authorization tokens

We have a lot of duplicated sql code that looks like this:

  if a_uid = 0 then
    raise 'User id 0 is not allowed to use this function.';;
  end if;;

  if a_api_key is not null then
    select user_id into a_user_id from users_api_keys
    where api_key = a_api_key and active = true and list_balance = true;;
  else
    a_user_id := a_uid;;
  end if;;

  if a_user_id is null then
    return;;
  end if;;

We need to abstract that into a more general function. pgsql is pretty awkward to work with, but I think we can deduplicate some of this code. The awkward part is that each type of permission is a column instead of a row. Maybe if we change that, it will make this task easier.

SEO

We should set some meta tags to improve our SEO rankings.

When a user requests to register the message should contain the email address

If someone types in the wrong email address when registering, they won't realize and will wait indefinitely for the email, which will cause a stuck user and the user will have to be restarted.

The current message is "Thank you. Please check your email for further instructions"

It should say "Thank you. An email has been sent to [email protected]. Please check your email for further instructions"

allow users to upload PGP keys

If users have 2 factor:

As long as the user has access to their password + 2 factor, they should be able to change their PGP key. As long as they have access to their PGP key, they should be able to reset they password and + 2 factor.

If they have no 2 factor:

As long as they have access to the email address or password, they should be able to set up a PGP key or 2 factor.
As long as they have access to the email, they should be able to reset the password.

ADMIN

How do you login as admin or access the database?

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.