Title: My new projet: an almost anonymous exchange market place Post by: grondilu on June 20, 2011, 03:08:04 PM Guys I'm so enthusiastic about this new project of mine that I can't resist publishing it even if it's currently a work in progress. The FAQ is already here, along with the command line help, and many of the difficult technical parts are done (signing, verifying and encrypting orders, protecting the database with locks, and so on). I think it is going to be pretty cool. Check it out: http://s0.barwen.ch/~grondilu/cgi-bin/euronymous It's 100% GNU/bash CGI :) Title: Re: My new projet: an almost anonymous exchange market place Post by: TheRandomGuy on June 20, 2011, 04:17:09 PM Nice!
Title: Re: My new projet: an almost anonymous exchange market place Post by: Nefario on June 20, 2011, 04:21:54 PM http://bitcoinweekly.com/articles/anonymous-money-needs-an-anonymous-exchange
Cough cough, should rewrite that faq. Title: Re: My new projet: an almost anonymous exchange market place Post by: Ian Maxwell on June 20, 2011, 04:42:30 PM So, if I'm understanding this correctly, most transactions require a signature (as opposed to a password)? Good, I was just envisioning something like that recently. It should be more secure overall---the only question is how to incorporate that into a web interface. Actually, are you planning on including a web interface?
Title: Re: My new projet: an almost anonymous exchange market place Post by: AntiVigilante on June 20, 2011, 04:47:35 PM So, if I'm understanding this correctly, most transactions require a signature (as opposed to a password)? Good, I was just envisioning something like that recently. It should be more secure overall---the only question is how to incorporate that into a web interface. Actually, are you planning on including a web interface? link is web based as I understand it. Title: Re: My new projet: an almost anonymous exchange market place Post by: TheBitMan on June 20, 2011, 05:27:20 PM Guys I'm so enthusiastic about this new project of mine that I can't resist publishing it even if it's currently a work in progress. The FAQ is already here, along with the command line help, and many of the difficult technical parts are done (signing, verifying and encrypting orders, protecting the database with locks, and so on). I think it is going to be pretty cool. Check it out: http://s0.barwen.ch/~grondilu/cgi-bin/euronymous It's 100% GNU/bash CGI :) http://i55.tinypic.com/2mn28ed.png Title: Re: My new projet: an almost anonymous exchange market place Post by: grondilu on June 21, 2011, 10:38:55 AM So, if I'm understanding this correctly, most transactions require a signature (as opposed to a password)? Good, I was just envisioning something like that recently. It should be more secure overall---the only question is how to incorporate that into a web interface. Actually, are you planning on including a web interface? There will be no HTML-form based interface. It's really a pain in the ass to program imho. And such things exist already. My plan is really to build a HTTP server for a command line client. The web server will only be used to publish informations and general help. When the site is ready the plan is to publish it on a hidden TOR server. Right now I'm publishing it with my real name as I see no way anyone can claim I am doing anything illegal. This site doesn't work yet so I can't do any actual trading. Publishing it is really a matter of free speech. Title: Re: My new projet: an almost anonymous exchange market place Post by: TheBitMan on June 21, 2011, 01:40:28 PM So, if I'm understanding this correctly, most transactions require a signature (as opposed to a password)? Good, I was just envisioning something like that recently. It should be more secure overall---the only question is how to incorporate that into a web interface. Actually, are you planning on including a web interface? There will be no HTML-form based interface. It's really a pain in the ass to program imho. And such things exist already. My plan is really to build a HTTP server for a command line client. The web server will only be used to publish informations and general help. When the site is ready the plan is to publish it on a hidden TOR server. Right now I'm publishing it with my real name as I see no way anyone can claim I am doing anything illegal. This site doesn't work yet so I can't do any actual trading. Publishing it is really a matter of free speech. Title: Re: My new projet: an almost anonymous exchange market place Post by: grondilu on June 22, 2011, 10:57:11 AM REMOVED
Title: Re: My new projet: an almost anonymous exchange market place Post by: Vinnie on June 22, 2011, 04:20:12 PM Looking forward to seeing it up and running! We need more tools like this to protect ourselves.
Title: Re: My new projet: an almost anonymous exchange market place Post by: brendio on June 23, 2011, 01:03:15 AM I haven't tried the interface, but from the manual, it seems that you can deposit and withdraw BTC or withdraw EUR, but cannot deposit EUR.
I was just wondering how that will work then if there is no EUR in the system to support buy orders. It's a bit like TradeHill at the moment. They have markets for about 20 currencies, but there's no way to submit a buy order for the 17 or so that do not yet accept deposits. Title: Re: My new projet: an almost anonymous exchange market place Post by: Ian Maxwell on June 23, 2011, 02:54:12 AM I was just coming here to ask the same question. If there's no way to deposit euros, who will give me euros for my bitcoins? Are you seeding it with your own capital or what?
Title: Re: My new projet: an almost anonymous exchange market place Post by: grondilu on June 23, 2011, 11:07:20 AM I haven't tried the interface, but from the manual, it seems that you can deposit and withdraw BTC or withdraw EUR, but cannot deposit EUR. I was just wondering how that will work then if there is no EUR in the system to support buy orders. It's a bit like TradeHill at the moment. They have markets for about 20 currencies, but there's no way to submit a buy order for the 17 or so that do not yet accept deposits. The site owner will be the only one who will be able of depositing paper currencies. So with this site, you CAN NOT buy bitcoins. But you can sell them. By the way, here is the latest version of my code. I have totally rewritten it: [code] #!/bin/bash THIS_IS_BETA() { true ; } content() { echo "Content-type: ${2:-text}/${1:-html};" ; echo ; } error() { content plain ; echo "$@" ; exit ; } # uncomment this for debugging #content plain ; exec 2>&1 ; set -e # Testing installations on server bash --version | grep -q -v ' [0-3]\.' || error "too old bash version. Please upgrade to >4.0" openssl version | grep --q -v ' 0\.[0-9]' || error "wrong openssl version. Please upgrade to >1.0." bc --version >/dev/null 2>&1 || error "missing bc. Please install the unix basic calculator." dc --version >/dev/null 2>&1 || error "missing dc. Please install the unix desk calculator." gawk --version >/dev/null 2>&1 || error "missing gawk. Please install GNU Awk." [[ -f base58.sh ]] || error "missing file base58.sh" . base58.sh || error "error in file base58.sh" # database protection unlock() { lockfile-remove "$0" ; } error() { unlock ; content plain ; echo "$@" ; exit ; } lock() { local maximum_number_of_lock_attempts=2 if [[ -n "$maximum_number_of_lock_attempts" ]] then lockfile-create -r "$maximum_number_of_lock_attempts" "$0" else lockfile-create "$0" fi || error "Could not lock the database. Please try again later." } # associative arrays to define different kinds of currencies declare -A smallest_notes=([EUR]=5 [USD]=1) declare -a paper_currencies=(${!smallest_notes
BTC="bitcoin" \ [eur]="euro" \ [usd]="U.S. dollar" \ [jpy]="japanese yen" \ [chf]="swiss franc" \ ) # a function to determin the kind of a currency currencyType() { local currency="${1^^}" if [[ "$currency" = 'BTC' ]] then echo "crypto" else for c in "${paper_currencies
if [[ "$currency" = "$c" ]] then echo "paper" ; return fi done echo "unknown" return 1 fi } # a function to compare floating point numbers compare() { bc <<<"if ($1 > $2) print \">\" else if ($1 < $2) print \"<\" else print \"=\"" } # a function to get account balance in any given currency getbalance() { case "${1,,}" in "$(THIS_IS_BETA || echo "btc")") bitcoind getbalance "$2" ;; *) # server has illimited deposit capability if [[ "$2" = "$server_account" ]] then echo 1000 else grep "^$2,${1^^}," "$0-moves.csv" | gawk -F, -v OFS=, -v s=0 '{ s+=$3 } END { print s }' fi ;; esac } # some regular expressions account_regex='^[a-z0-9]{40}$' amount_regex='(0|0{,1}\.[0-9]+|[1-9][0-9]*\.[0-9]+|[1-9][0-9]*)' # prevent use of real bitcoind for now # (additionnal security to THIS_IS_BETA) bitcoind() { : ; } # server parameters admin="XXXXXX" server_privkey="-----BEGIN PRIVATE KEY----- XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX -----END PRIVATE KEY-----" server_pubkey() { openssl pkey -pubout <<<"$server_privkey" ; } server_account="$( openssl pkey -pubout <<<"$server_privkey" | openssl dgst -rmd160 -binary | xxd -p)" # command line client function # requires curl, openssl version >1, xxd euronymousClient() { #you may have to modify this line manually local url="http://localhost/cgi-bin/euronymous" case "${1,,}" in getnewaddress) if [[ -n "$2" ]] then curl -s "$url?getnewaddress&account=$2" elif ! local privkey="$(openssl genpkey -algorithm RSA)" then echo "could not create private key" 2>&1 ; return 1 elif ! local account="$( openssl pkey -pubout <<<"$privkey" | openssl dgst -rmd160 -binary | xxd -p)" then echo "could not compute rmd160 of public key" 2>&1 ; return 2 elif ! gpg -e -r "$USER" <<<"$privkey" > "$account.pem.gpg" then echo "could not encrypt private key" 2>&1 ; return 3 else echo "created ./$account.pem.gpg" 2>&1 $FUNCNAME getnewaddress "$account" fi ;; withdraw|transfer|trade|cancel) local client_privkey="$(cat)" command="$(date +%s) $@" curl -s -d "$( if [[ "${1,,}" = "withdraw" ]] && [[ "${3,,}" = "eur" ]] then echo "encrypted:" openssl pkeyutl -encrypt -pubin -inkey <(curl -s "$url?pubkey") | xxd -p else cat fi <<<"$command" openssl pkey -pubout <<<"$client_privkey" openssl dgst -rmd160 -sign <(echo "$client_privkey") -binary <<<"$command" | xxd -p )" "$url" ;; getbalance) curl -s "$url?getbalance¤cy=$2&account=$3" ;; view) local order="$(curl -s "$url?order=$2")" if [[ "$order" = "no such order" ]] then return 1 elif echo "$order" grep -q "^encrypted:$" <<<"$order" then local client_privkey="$(cat)" if [[ -n "$client_privkey" ]] then echo "Decrypted command:" sed ' 1,2d /-BEGIN PUBLIC KEY-/,$d ' <<<"$order" | xxd -p -r | openssl pkeyutl -decrypt -inkey <(echo "$client_privkey") 2>&1 fi fi ;; *) echo "usage: $FUNCNAME {create|getnewaddress|withdraw|trade|cancel} [arguments...] For more help, visit $url?help" >&2 return 2 ;; esac } clientcode() { sed -n '/^# command line client function/,/^}$/p' "$0"; } # Ok now the real CGI part... # GET requests if [[ "$REQUEST_METHOD" = "GET" ]] then case "$QUERY_STRING" in "") # home page content echo " <title>$0</title> <h1>$0: almost anonymous currency exchange marketplace</h1> <ul> <li><a href=$0?faq>F.A.Q.</a> <li><a href=$0?book>trading book</a> <li><a href=$0?orders>full list of all orders</a> (<a href=$0?orders&format=csv>CSV</a>) <li><a href=$0?moves>adjudications, transfers, withdrawals and deposits</a> (<a href=$0?moves&format=csv>CSV</a>) <li><a href=$0?help>help for the command line client</a> <li><a href=$0?source_code>source code of this site</a> (<a href=$0?source_code=client>client only</a>) <li><a href=$0?postal_fees>postal fees</a> </ul> <p>Last adjudication: (TODO)</p> <p>You can see which bitcoin addresses are associated to a given account with this form:<br> <form action=$0 method=get> <input type=hidden name=show value=addresses> <input type=text name=account size=40> <input type=submit value=\"see addresses\"> </form> </p> <p>Our <a href=$0?pubkey>public key</a>:<xmp>$(server_pubkey)</xmp></p> " ;; book) # display trading book in HTML table content plain join -t, -v 1 <( sort -t, "$0-trade-orders.csv" ) <( sort -t, "$0-cancelled-trades.csv" ) | cut -d, -f 4 ;; orders) # display all command history in a big HTML table content echo "<title>$0 list of all orders</title> <table width=75%> <thead align=left> <tr> <th>reference</th><th>account</th><th>date</th><th>command</th> </tr> </thead> <tbody>" cat "$0-"{withdraw,trade,transfer,cancel}-orders.csv | cut -d, -f 1,2,3,4 | sort -t, -g -k 3 | while IFS=, read ref account date command do echo " <tr> <td><a title=$ref href=$0?order=$ref name=$ref>${ref::5}...${ref: -2}</a></td> <td><a title=$account>${account::8}...${account: -3}</a></td> <td><a title=\"$(date -d @$date)\">$(date -d @$date +"%F %R")</td> <td>$( case "$command" in cancel' '*) cancelled_order="${command#* }" echo "cancel <a href=#$cancelled_order>${cancelled_order::6}...${cancelled_order: -3}</a>" ;; transfer' '*) destination_account="${command##* }" echo "${command% *} <a title=$destination_account>${destination_account::8}...${destination_account: -3}</a>" ;; *) echo "$command" ;; esac ) </td> </tr>" done echo " </tbody></table>" ;; orders'&'format=csv) # loads orders in CSV format content csv cat "$0-"{withdrawal,trading,transfer,cancel}"-orders.csv" ;; moves) # view of all accounting entries content echo "TODO" ;; moves'&format=csv') # loads accounting entries in CSV format content csv echo "TODO" ;; faq) # Frequently Asked Question HTML page content echo " <title>$0 Frequently Asked Questions</title> <h1>$0 F.A.Q.</h1> <h2>What is the purpose of this site?</h2> <p>This site aims to be a more or less anonymous bitcoin exchange marketplace. By more or less, we mean that our priority is to provide anonymity for us, not for you. Our main goal is to prevent government from shutting our site down.</p> <p>The reason we can not provide you any full anonymity, is that we will need your postal address to send you your euros. However, your accounts are anonymous and you can create as many of them as you want. Therefore, we have no way to know exactly the total amount of money you own in our book. This ignorance offers you some protection.</p> <h2>What can I do on this site?</h2> <p>You can trade bitcoins against other national currencies, mainly euros. You can create accounts, deposit bitcoins, withdraw bitcoins, withdraw euros via cash in the mail, and trade bitcoins/euros on your account against euros/bitcoins on some other account.</p> <h2>What can I NOT do on this site?</h2> <p>You can NOT send us national currencies. Receiving national currencies anonymously is almost impossible (if you know a method, please let us know). Therefore, you can only fund your account using bitcoins. If you want to sell your national currencies in cash, we suggest you mirror this site.</p> <h2>Do you plan on publishing my postal address?</h2> <p>No, we will publish an encrypted version of the address. Only the owner of the account will be able to decrypt it, so he can verify it was transmitted correctly.</p> <p>We shall, however, always publish the signature of each order, so that we can prove our good faith in case of a disagreement.</p> <h2>Why are you not online all the time?</h2> <p>We have our reasons.</p> <p>We shall try to be online at least a few hours every day, though. In the future, it should be possible to submit orders with anonymous email via i2p for instance.</p> <p>Right now, you can ping our webserver to check if we are online:</p> <xmp>$ ping -q -c 5 $HTTP_HOST</xmp> <p>Use this command in scripts if you want an order to be sent as soon as the server is back online.</xmp> " ;; help) # command line client help HTML page content echo " <title>$0 command line client help</title> <h1>Sendings orders on command line</h1> <p>To send commands you must use a bash command line function which is <a href=$0?source_code>published with the server's source code</a>. </p> <p>Here it is for convenience:</p> <textarea rows=10 cols=80 readonly=yes>$(clientcode)</textarea> <h2>Creating an account</h2> <p>An account number is just the rmd160 of a public key. Creating one can be done offline since no commmunication with the server is necessary.</p> <p>Although the creation of an account can be made easy with our client (see below), you can do it manually on your prefered shell command line. Just run:</p> <xmp>$ openssl genpkey -algorithm RSA</xmp> <p>This will print on stdout a RSA private key that will be perfectly suitable as a private key for an account on our server. However, for better security, you might want to encrypt the output using GPG: </p> <xmp>$ openssl genpkey -algorithm RSA | gpg -e -r \$USER > priv.pem.gpg</xmp> <p>To get the account number, you can run:</p> <xmp>$ gpg < priv.pem.gpg | openssl dgst -rmd160</xmp> <p>You might then want to copy paste the account number in order to rename the file priv.pem.gpg:</p> <xmp>$ mv {priv,ACCOUNT_NUMBER}.pem.gpg</xmp> <p>Of course, you can write your own shell functions to automize this.</p> <h2>Deposit bitcoins</h2> <p>To deposit some bitcoins on your $0 account, you need to request a bitcoin address where to send some bitcoins. So basically you will ask the server to run a <i>getnewaddress</i> bitcoin command.</p> <p>This can be done only once, or as many times as you want. It's up to you.</p> <p>If you have already created an account as explained above, you can run:<p> <xmp>$ euronymousClient getnewaddress ACCOUNT_NUMBER</xmp> <p>On the server side, this command will execute:</p> <xmp>bitcoind getnewaddress ACCOUNT_NUMBER</xmp> <p>Thus creating the appropriate bitcoin account if it doesn't exist already.</p> <p>The command will print the generated bitcoin address on stdout. You can then use this address to fund your account.</p> <p>If you had not already created an account, you can have the client create one for you by running the getnewaddress command with no account number:</p> <xmp>$ euronymousClient getnewaddress</xmp> <p>Along with the bitcoin address on stdout, this command will also create a private key in an ACCOUNT_NUMBER.pem.gpg file in the current working directory.</p> <p>You can retrieve a signed list of bitcoin addresses associated to an account at this url (there is also a small html form on the home page to do this):</p> http://$HTTP_HOST/cgi-bin/$0?show=addresses&account=ACCOUNT_NUMBER <p>This removes to us plausible deniability of an association between a bitcoin address and one of your accounts. We suggest you keep a copy of this list for each of your accounts.</p> <h2>Withdraw bitcoins</h2> <p>To withdraw some bitcoins, you need to provide a bitcoin address and an amount of bitcoins you want to receive.</p> <xmp>$ euronymousClient withdraw AMOUNT btc to BITCOIN_ADDRESS</xmp> This command will read the private key from stdin, so a complete command could be: <xmp>$ euronymousClient withdraw AMOUNT btc to BITCOIN_ADDRESS < ACCOUNT_NUMBER.pem</xmp> <p>Notice that in most shells you can place the redirection wherever you want on the command. Thus you could as well have entered:</p> <xmp>$ euronymousClient <ACCOUNT_NUMBER.pem withdraw AMOUNT btc to BITCOIN_ADDRESS</xmp> <p>You can use GnuPG for more security:</p> <xmp>$ gpg < ACCOUNT_NUMBER.pem.gpg | euronymousClient withdraw AMOUNT btc to BITCOIN_ADDRESS</xmp> <p>Or:</p> <xmp>$ <ACCOUNT_NUMBER.pem.gpg gpg| euronymousClient withdraw AMOUNT btc to BITCOIN_ADDRESS</xmp> <h2>Withdraw euros</h2> <p>To withdraw euros, you need to provide a postal address where to receive cash via mail. Only use multiples of 5 (in order to use only bank notes). Postal fees will be deducted from your euro account. For instance, if you withdraw ten euros, ten euros will be sent but 10.55 euros will be deducted from your euro balance.</p> <xmp>$ euronymousClient withdraw AMOUNT eur to POSTAL_ADDRESS</xmp> <p>Again, this command reads the private key from stdin.</p> <p>POSTAL_ADDRESS should be a double or single quote enclosed string. Please do not put any carriage return or other fancy character in the address. It might false the signature process. Use a semi-colon (;) if you want to specify a carriage return.</p> <p>Exemple:</p> <xmp>$ euronymousClient withdraw 50 eur to \"Satoshi Nakamoto;42, unknown street,;Tokyo, JAPAN\"</xmp> <p>For this kind of order, the command is not sent in clear through the internet. Instead, it is encrypted with the server's <a href=$0?pubkey>public key</a>.</p> <h2>Transfer funds from one account to another</h2> <p>To do so you can run:</p> <xmp>$ euronymousClient transfer AMOUNT {eur|btc} to ACCOUNT_NUMBER</xmp> <p>AMOUNT should be a positive number. This commands reads private key from stdin.</p> <h2>Trade bitcoins vs. euros</h2> <p>To submit a trading order, you run a command such as:</p> <xmp>$ euronymousClient trade 5.982 btc -19.43 eur</xmp> <p>Use signed values to indicate the direction of your trade: negative for the currency you want to sell, positive for the currency you want to buy.</p> <p>Only use three letters currency ISO code.</p> <p>This command also reads the private key from stdin.</p> <p>You can use shell expansion magic if you want to make a trade on a more conventionnal price/amount notation.</p> <p>Example: buying 50 bitcoins at 16.4 EUR/BTC</p> <xmp>$ amount=50 price=16.4; euronymousClient trade \$amount btc -\$(dc <<<\"4k \$amount \$price *n\") eur</xmp> <h2>Cancel an order</h2> <p>Euro withdrawals and trade orders are the only orders you can cancel.</p> <p>You can cancel a trading order as long as the order has not been fully executed. Cancellation of a partially executed trading order will only prevent the rest of the trade to be adjudicated. <p>You can cancel a euro withdrawal as long as the letter has not been sent yet.</p> <p>To cancel an order, just run:</p> <xmp>$ euronymousClient cancel REFERENCE_NUMBER</xmp> <p>REFERENCE_NUMBER is a reference number published in the <a href=$0?orders>list of all orders</a>. It is actually the md5sum of the signature.</p> <p>This command reads the private key from stdin.</p> <h2>Checking</h2> <p>You can visualize an order, whether it is a trading, withdrawal or cancelling order, by running:</p> <xmp>$ euronymousClient view ORDER_REFERENCE_NUMBER</xmp> <p>If the order is a euro withdrawal order, thus containing a postal address, then the command will read the private key from standard input in order to decrypt the command.</p> " ;; order=*) # viewing specific order ref="${QUERY_STRING#*=}" content plain if ! grep -q "^$ref$" "$0.orders" then echo "no such order" else sed -n "/^$ref$/,/^$/ {/^.*$/p}" "$0.orders" fi ;; getbalance'&'currency=*'&'account=*) # balance inquiry currency="${QUERY_STRING#*=}" currency="${currency%%&*}" account="${QUERY_STRING##*=}" content plain getbalance "$currency" "$account" ;; pubkey) # Server's public key displaying request content plain server_pubkey ;; show=addresses'&'account=*) # displaying bitcoin addresses associated to a given, specific account account="${QUERY_STRING##*=}" [[ "$account" =~ $account_regex ]] || error "'$account' is not a valid account format" content plain server_pubkey { echo "Here are the bitcoin addresses for account ref. $account:" if THIS_IS_BETA then echo NONE else list="$(bitcoind getaddressesbyaccount "${QUERY_STRING#*=}")" echo "${list:-NONE}" fi } | tee >( openssl dgst -rmd160 -sign <(echo "$server_privkey") -binary | xxd -p ) ;; source_code) # server's source code request content plain # some portions of the code must be hidden sed -r ' /^admin=.*/s/.*/admin=XXXXXXXXX/ /^rpcpasswd=/s/.*/rpcpasswd=XXXXXXXX/ /^server_privkey="-----BEGIN PRIVATE KEY-----/,/-----END PRIVATE KEY-----"$/ { s/.{64}/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/ s/.*==$/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/ }' "$0" ;; source_code=client) # source code request (only the client part) content plain clientcode ;; getnewaddress'&'account=*) # getnewaddress command account="${QUERY_STRING##*=}" [[ "$account" =~ $account_regex ]] || error "wrong account format" bitcoin_address="$(THIS_IS_BETA || bitcoind getnewaddress "$account")" || error "could not generate address :(" content plain sleep 5 # we make the client wait a bit to prevent abuse echo "$bitcoin_address" ;; server_info) # server information request content plain set ;; *) # error error "unknown query string: $QUERY_STRING" ;; esac fi # POST requests if [[ "$REQUEST_METHOD" = "POST" ]] then # reading post data # # post data is supposed to be made of: # - the command # - the client's public key # - the signature of the command, corresponding to the given public key read -N $CONTENT_LENGTH post_data || error "could not retrieve post data" # extracting public key first pubkey="$(sed -n '/^-\+BEGIN PUBLIC KEY-\+$/,/^-\+END PUBLIC KEY-\+$/p' <<<"$post_data")" # if there is no public key, then there is no point going further. [[ -n "$pubkey" ]] || error "no public key in post data" # checking that the public key is a valid one openssl pkey -pubin -pubout <<<"$pubkey" >/dev/null || error "invalid public key in post data" # now that we have the client's public key, we can compute the # corresponding account number account="$(openssl dgst -rmd160 -binary <<<"$pubkey" |xxd -p)" # extracting signature signature="$(sed '1,/^-\+END PUBLIC KEY-\+$/d' <<<"$post_data")" # all commands in POST requests must be signed so if there is no signature, we stop here [[ -n "$signature" ]] || error "no signature in post data" # extracting the command command="$(sed '/^-\+BEGIN PUBLIC KEY-\+$/,$d' <<<"$post_data")" # if command begins with "encrypted:", then it is encrypted with the # server's public key. This happens when the command is a paper currency # withdrawal, as such a command has a postal address in it. # In that case, we just have to decrypt it first. if [[ "$command" =~ ^encrypted: ]] then command="$(xxd -p -r <<<"${command#encrypted:}" | openssl pkeyutl -decrypt -inkey <(echo "$server_privkey"))" || error "could not decrypt command" fi # now we check the signature <<<"$command" openssl dgst -rmd160 \ -verify <(echo "$pubkey") -signature <(xxd -p -r <<< "$signature") || error "wrong signature" # The signature is correct, we can make a reference number out of it. # this is used as a unique identifier for all orders reference="$(openssl dgst -md5 -binary <<<"$signature" | xxd -p)" # checking that the reference is not already in the orders file # (the database is not locked yet so we'll have to check that again later) grep -q "^$reference$" "$0.orders" && error "this order has already been submitted" # We put the command words in an array. It will help parsing read -a command_array <<<"$command" # first word shoud be a time in seconds since EPOCH date="${command_array[0]}" [[ "$date" =~ ^[1-9][0-9]*$ ]] || error "wrong date format" # comparing given time with server time now="$(date +%s)" acceptable_delay_in_minutes=2 ((date<now-60*acceptable_delay_in_minutes)) && error "claimed date ($(date -d @$date)) is more than $acceptable_delay_in_minutes minutes in the past" # The server won't accept an order which pretends to be coming from the future. ((date>now)) && error "claimed date ($(date -d @$date)) is in the future" # We store the base properties of order in a pre CSV record order="$reference,$account,$date" # LOCKING THE DATABASE # We're about to parse the command. As we do, we'll extract data from the # database, and we'll do many consistency check. We don't want these data # to have changed once we commit to the actual database edition. So we # lock the database NOW. lock # Let's check again that the order is not already in the database ! grep -q "^$reference$" "$0.orders" || error "this order has already been submitted" # First command word was the time. We've already extracted it. The second # word is the type of the order. We deal with the different # possibilities in a case block. # Each kind of order has its own format for storage. There is a common # $0.orders file, though. case "${command_array[1]^^}" in WITHDRAW) # withdraw order # specific file for withdrawal orders is "$0-withdraw-orders.csv" order_file="$0-withdraw-orders.csv" # command should be of the form: # TIME withdraw AMOUNT CURRENCY to DESTINATION # DESTINATION could be several words, # so the command should have at least 6 words [[ "${#command_array
# Third word is the amount to be withdrawned amount="${command_array[2]#+}" [[ "$amount" =~ ^$amount_regex$ ]] || error "wrong amount format or negative amount" # it should be positive [[ "$amount" -ge 0 ]] || error "null amount in a withdrawal order" # the 'to' preposition is not optionnal [[ "${command_array[4]^^}" = "TO" ]] || error "wrong command format (was expecting 'to', not '${command_array[4]}')" # storing currency name in lower case currency="${command_array[3],,}" # checking balance balance="$(getbalance "$currency" "$account")" || error "could not get $currency balance for account $account" # checking that there is enough funds for the requested # withdrawal amount [[ "$(compare "$amount" "$balance")" = '<' ]] || error "not enough ${humanCurrencyNames[$currency]:-$currency} funds on this account" # Now, depending on whether we're dealing with a cryptographic # currency or a paper currency, the procedure will not be the # same. A cryptocurrency can be withdrawned electronically, # but a paper currency must be sent via postal mail. case "$(currencyType "$currency")" in crypto) # so far bitcoin is the only cryptocurrency, so we'll # just assume we're dealing with bitcoins bitcoin_address="${command_array[5]}" checkBitcoinAddress "$bitcoin_address" || error "invalid bitcoin address" order+="${command#* },$currency,$amount,$bitcoin_address" bitcoind_args=(sendfrom "$account" "$bitcoin_address" "$amount" "${minconf:=1}" "$reference") if THIS_IS_BETA then echo "$(date): bitcoind ${bitcoind_args
: bitcoind "${bitcoind_args
;; paper) humanName="${humanCurrencyNames[$currency]:-$currency}" # paper currencies can only be sent via postal mail if the # amount is a multiple of the smallest bank note in this # currency smallest_note="${smallest_notes["${currency^^}"]}" [[ "$(dc <<<"$amount $smallest_note/$smallest_note*n")" = "$amount" ]] || error "amount in $humanName should be a multiple of $smallest_note in order to be sent via postal mail" # for a paper withdrawal we can't store the full command order+=",$amount $humanName withdrawal,$currency,$amount" if ! THIS_IS_BETA then # Mail instructions to administrator { gpg -ae -r "$admin" 2>/dev/null || cat } <<<" order ref. $reference (account n° $account): ${command#* } " | mail -s "$amount $humanName withdrawal" "$admin" & fi # encrypt command to hide the address command="encrypted:" command+="$(openssl pkeyutl -encrypt -pubin -inkey <(echo "$pubkey") <<<"$command")" ;; *) error "unkown currency (or not supported yet)" ;; esac moves=("$account,${currency^^},-$amount") ;; TRADE) # trade order # specific file for trade orders is "$0-trade-orders.csv" order_file="$0-trade-orders.csv" # command should be of the form: # TIME trade AMOUNT1 CURRENCY1 AMOUNT2 CURRENCY2 # considering the format of a trade order, the command array # should be six words long. [[ "${#command_array
# extracting amounts and currencies amounts=("${command_array[2]}" "${command_array[4]}") currencies=("${command_array[3]}" "${command_array[5]}") humanNames=() for c in "${currencies
done # checking amounts declare -i n i for i in 0 1 do # checking format [[ ! "${amounts}" =~ ^[+-]{,1}$amount_regex$ ]] && error "wrong amount format for currency '${currencies}'" # detecting the negative amount [[ "${amounts::1}" = '-' ]] && n=i # detecting a null amount ((${amounts%.*})) || error "'${currencies}' amount is null" done # checking that amounts don't have the same sign ((${amounts[0]%%.*}*${amounts[1]%%.*} < 0)) || error "amounts have the same sign" # checking balance balance="$(getbalance "${currencies[n]}" "$account")" || error "could not check balance" # checking funds [[ "$(compare "${amounts[n]:1}" "$balance")" = '>' ]] || error "not enough funds" order+=",${command#* }" moves=() for i in 0 1 do order+=",${amounts},${currencies}" moves+=("$account,${amounts},${currencies},$reference") done ;; TRANSFER) amount_to_transfer="${command_a Title: Re: My new projet: an almost anonymous exchange market place Post by: Nefario on June 23, 2011, 06:33:22 PM That is one long bloody error message.
Title: Re: My new projet: an almost anonymous exchange market place Post by: grondilu on June 24, 2011, 10:59:23 AM This project is turning me crazy. First I realised there is no reason to limit the currencies to bitcoin and euros. Then I realized there is no reason to limit it to currencies. So I changed it and started to developp a project that kind of looks like the loom project. But then I had an even crazier idea: what about decentralizing adjudication? The idea would be to use bitcoin-like concepts to distribute the adjudication process amongst the clients. Each of them would compute a proof-of-work on the book of the orders they know about. The winner publishes its results and gets rewarded by the arbitrage opportunities he could exploit in his order book. http://s0.barwen.ch/~grondilu/cgi-bin/catalaxia Title: Re: My new projet: an almost anonymous exchange market place Post by: marcus_of_augustus on June 24, 2011, 11:13:53 AM This project is turning me crazy. First I realised there is no reason to limit the currencies to bitcoin and euros. Then I realized there is no reason to limit it to currencies. So I changed it and started to developp a project that kind of looks like the loom project. But then I had an even crazier idea: what about decentralizing adjudication? The idea would be to use bitcoin-like concepts to distribute the adjudication process amongst the clients. Each of them would compute a proof-of-work on the book of the orders they know about. The winner publishes its results and gets rewarded by the arbitrage opportunities he could exploit in his order book. http://s0.barwen.ch/~grondilu/cgi-bin/catalaxia Step away from the keyboard? Title: Re: My new projet: an almost anonymous exchange market place Post by: FreddyFender on June 24, 2011, 01:54:26 PM THX Grondilu
You saved me some code hacking. You should change your name to Bashman! |