В данном топике хочу рассказать о своих потугах написать на питоне биллинг для практически любого проекта на основе bitcoin.
Материал сырой, кодер я не супер, поэтому критика принимается.
Поехали...
Первое что нам понадобится - сервер. Я использовал debian linux (свой любимый) 64 bit.
Нам для старта понадобится скачать оффициальный клиент bitcoin. Download page
Скачиваем клиент, распаковываем в произвольную папку пользователя.
В моем случае используется /home/usr/bitcoind
Переходим в папку bin/64/
Запускаем ./bitcoind
Все что необходимо он уже создал. Далее нам предстоит настроить данный софт.
Пишем в консоль killall bitcoind
Идем по адресу /home/usr/.bitcoin
И создаем тут файл конфигурации. mcedit bitcoin.conf
Я использовал следующие настройки:
Возвращаемся в папку /home/usr/bitcoind/bin/64
Стартуем демон снова ./bitcoind
Все. Наш клиент стал демоном и начал синхронизировать блоки.
Для любопытных - вторая строка - это настройка работы биткоин через сеть тор. У меня на сервере он установлен, но для ускорения синхронизации не используется.
Далее примем за аксиому тот момент, что я сам пишу софт и отталкиваюсь от того что мне в голову стукнет. А мои клиенты все определяются по jabber аккаунту.
Я создаю следующие папки:
/home/usr/bitcoind/src/
/home/usr/bitcoind/src/db/
Выставляю права 777 на папку db. Это важно.
И создаем следующие файлы:
cat>btc.log
chmod 777 btc.log
mcedit btc.py
Протокол запросов идет у нас шифрованным. Ключ один, но можно использовать два. Один от клиента второй от сервера.
Принцип работы прост. Есть демон и есть бд. Что бы не дергать демон каждый раз я записываю данные в БД. Сделал специально на sqlite для большей портабельности.
Код клиента:
Клиент первым делом шифрует ключевую фразу и шлет серверу. Если все ок - сервер отвечает шифрованным true. Ну и дальше идет запрос на клиента (отправляем жабу или мыло), ответ BTC адрес.
В данный момент чего не доделал:
1. определение у кого какой балланс
2. отправку комманды на пополнение балланса в панель клиента
3. перекидывание денег с сервака биллинга мне на кош.
Написано данное чудо просто от балды. От большого нехер делать и может быть кому-то полезно. Жду реакции и критики кода. А так же желающих доработать данное творчество.
Материал сырой, кодер я не супер, поэтому критика принимается.
Поехали...
Первое что нам понадобится - сервер. Я использовал debian linux (свой любимый) 64 bit.
Нам для старта понадобится скачать оффициальный клиент bitcoin. Download page
Скачиваем клиент, распаковываем в произвольную папку пользователя.
В моем случае используется /home/usr/bitcoind
Переходим в папку bin/64/
Запускаем ./bitcoind
Все что необходимо он уже создал. Далее нам предстоит настроить данный софт.
Пишем в консоль killall bitcoind
Идем по адресу /home/usr/.bitcoin
И создаем тут файл конфигурации. mcedit bitcoin.conf
Я использовал следующие настройки:
Код:
daemon=1
gen=0
#proxy=127.0.0.1:9050
dns=1
upnp=1
noirc=1
server=1
rpcuser=usr
rpcpassword=fake_passwords
rpcport=8455
rpctimeout=30
paytxfee=0.0002
addnode=69.207.126.238:8333
addnode=73.189.41.65:8333
addnode=69.65.67.66:8333
connect=69.207.126.238:8333
connect=73.189.41.65:8333
connect=69.65.67.66:8333
Возвращаемся в папку /home/usr/bitcoind/bin/64
Стартуем демон снова ./bitcoind
Все. Наш клиент стал демоном и начал синхронизировать блоки.
Для любопытных - вторая строка - это настройка работы биткоин через сеть тор. У меня на сервере он установлен, но для ускорения синхронизации не используется.
Далее примем за аксиому тот момент, что я сам пишу софт и отталкиваюсь от того что мне в голову стукнет. А мои клиенты все определяются по jabber аккаунту.
Я создаю следующие папки:
/home/usr/bitcoind/src/
/home/usr/bitcoind/src/db/
Выставляю права 777 на папку db. Это важно.
И создаем следующие файлы:
cat>btc.log
chmod 777 btc.log
mcedit btc.py
Код:
#!/usr/bin/env python
#-*- coding: utf-8 -*-
# ----------------------------------------------------------
# coded by ar3s
# How to use: python btc-e.py
# Profit!
# ----------------------------------------------------------
import os
import sys
import time
import json
import base64
import hashlib
import urllib2
import datetime
import socket
import sqlite3
import subprocess
from Crypto.Cipher import AES # encryption library
#system
os.system('clear')
#sqlite
conn = sqlite3.connect('db/base.db')
conn.isolation_level = None
conn.text_factory = str
#crypt
BLOCK_SIZE = 32
PADDING = '{'
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
cipher = AES.new('Jns70wJnc92LmaTw')
def log(log):
if (len(log) != 0):
now = datetime.datetime.now()
f = open('btc.log', 'a')
f.write(str(now.day)+"."+str(now.month)+"."+str(now.year)+" "+str(now.hour)+":"+str(now.minute)+":"+str(now.second)+" - "+log+"\n")
f.close()
else:
print "enter a log data"
def rate():
response = urllib2.urlopen(urllib2.Request(url='https://btc-e.com/api/2/btc_usd/ticker'))
objFromJSON = json.loads(response.read())
ticker = objFromJSON['ticker']
return format(ticker['last'])
def bitcoin(cmd, jid):
if (cmd == "bal"):
try:
cmd = './bitcoind getbalance'
PIPE = subprocess.PIPE
p = subprocess.Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=subprocess.STDOUT, close_fds=True, cwd='/home/usr/bitcoind/bin/64/')
bal = p.stdout.read()
bal = float(bal.replace('\n',''))
return bal
except:
print "bitcoind not respond a ballance"
if (cmd == "add"):
try:
cmd = './bitcoind getnewaddress '+jid
PIPE = subprocess.PIPE
p = subprocess.Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=subprocess.STDOUT, close_fds=True, cwd='/home/usr/bitcoind/bin/64/')
btc = p.stdout.read()
btc = btc.replace('\n','')
except:
print "bitcoind not respond a BTC address"
return btc
if (cmd == "pars"):
ball = 0.0
account = ""
try:
cmd = './bitcoind listaccounts'
PIPE = subprocess.PIPE
p = subprocess.Popen(cmd, shell=True, stdin=PIPE, stdout=PIPE, stderr=subprocess.STDOUT, close_fds=True, cwd='/home/usr/bitcoind/bin/64/')
btc = p.stdout.read()
# сделать парсинг не нулевых баллансов и возврат имени и суммы в запрос
except:
log("bitcoind send not finished")
return account, ball
def sql(query):
#--------------------------
# Коннектимся к Базе данных
#--------------------------
connection = 0
try:
#conn = sqlite3.connect(":memory:")
cur = conn.cursor()
connection = 1
except sqlite3.Error:
connection = 0
log("Соединение с БД НЕ установлено!!!")
if ((query=='def') and (connection == 1)):
#print "Исполняем def запрос"
try:
cur.execute("Select * from user")
conn.commit()
#print "DEF запрос прошел успешно"
except:
print 'db not issue. Creating.'
cur.execute('''CREATE TABLE [user] ([id] INTEGER NOT NULL ON CONFLICT ABORT PRIMARY KEY ON CONFLICT ABORT AUTOINCREMENT, [jid] CHAR NOT NULL ON CONFLICT ABORT, [btc] CHAR NOT NULL ON CONFLICT ABORT, [ballance] FLOAT NOT NULL ON CONFLICT ABORT DEFAULT 0)''')
cur.execute("insert into user values (null,'ar3s@dlab.im','FakeAddress','0')")
conn.commit()
if ((query != 'def') and (connection == 1)):
#print "Исполняем запрос на пользователя"
# Тут проверяем имеется ли такой пользователь
btc = ""
jid = query
#print "Проверка по БД"
try:
cur.execute("select btc from user where jid=?",(jid,))
conn.commit()
except:
print "BAD sql query in section select BTC from DB"
#print "Парсим результат"
data = cur.fetchall()
if (len(data) != 0):
#print "Вошли в проверку"
adr = str(data[0])
adr = adr.split("'")
btc = adr[1]
#print btc
#print "Распарсили"
else:
# если ответ нулевой - то создаем пользователя
btc = bitcoin("add", jid)
print "Добавляем пользователя "+jid+":"+btc+"\n"
try:
cur.execute("insert into user values (null,?,?,'0')",(jid,btc,))
conn.commit()
except:
print "Error in sql query for add user in DB"
return btc
def crypt(msg):
EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
encoded = EncodeAES(cipher, msg)
return encoded
def decrypt(msg):
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
decoded = DecodeAES(cipher, msg)
return decoded
def main():
#-------------------------------
# Тест записи в лог
log("start")
#-------------------------------
# Читаем курс
kurs = rate()
print "Текущий курс BTC=>USD:"+kurs
log("Текущий курс BTC=>USD:"+kurs)
#-------------------------------
# читаем наш балланс из демона
bal = bitcoin("bal", "")
print "Текущий балланс кошельков:"+str(bal)
log("Текущий балланс кошельков:"+str(bal))
if (bal > 0):
account, ball = bitcoint("pars", "")
# тут сделать зачисление на балланс и отправку мне на кош
#-------------------------------
# Инициализируем БД
sql("def")
log("Инициализируем БД")
#-------------------------------
# инициализируем чтение сокета
try:
sock = socket.socket()
sock.bind(('', 4563))
sock.listen(1)
except Exception as e:
log("Не могу открыть сокет: %s" % e)
sys.exit()
while True:
srv, addr = sock.accept()
log("Socket opened: %s" % str(addr))
data = srv.recv(1024)
data = decrypt(data)
if data == 'PPDvtmw1POWFSkwmNH61WF0Vlhvhq5Gc':
log("Проверка ключа прошла успешно")
srv.send(crypt('true'))
data = '' # обнуляем данные от прошлого запроса
while 1: # ждем запрос от клиента
data = srv.recv(1024)
if data:
break
jid = decrypt(data)
if jid:
print jid
btc = sql(jid)
print "user "+jid+" : "+ btc
srv.send(crypt(btc))
log("Answer sendet")
else:
srv.send("error!")
log("!!! Проверка ключа НЕ прошла")
srv.close()
# start main function
if __name__ == '__main__':
main()
#--------------------------------------------------------------------------------------------------------------
# Happy end!
#--------------------------------------------------------------------------------------------------------------
Протокол запросов идет у нас шифрованным. Ключ один, но можно использовать два. Один от клиента второй от сервера.
Принцип работы прост. Есть демон и есть бд. Что бы не дергать демон каждый раз я записываю данные в БД. Сделал специально на sqlite для большей портабельности.
Код клиента:
Код:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#http://stackoverflow.com/questions/2490334/simple-way-to-encode-a-string-according-to-a-password
import socket
import base64
import hashlib
from Crypto.Cipher import AES # encryption library
BLOCK_SIZE = 32
PADDING = '{'
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
cipher = AES.new('Jns70wJnc92LmaTw')
def crypt(msg):
EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
encoded = EncodeAES(cipher, msg)
return encoded
def decrypt(msg):
DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
decoded = DecodeAES(cipher, msg)
return decoded
sock = socket.socket()
sock.connect(('127.0.0.1', 4563))
sock.send(crypt('PPDvtmw1POWFSkwmNH61WF0Vlhvhq5Gc'))
data = sock.recv(1024)
data = decrypt(data)
print data
if (data == 'true'):
sock.send(crypt('new_user@server.im'))
data = sock.recv(1024)
data = decrypt(data)
print data
sock.close()
Клиент первым делом шифрует ключевую фразу и шлет серверу. Если все ок - сервер отвечает шифрованным true. Ну и дальше идет запрос на клиента (отправляем жабу или мыло), ответ BTC адрес.
В данный момент чего не доделал:
1. определение у кого какой балланс
2. отправку комманды на пополнение балланса в панель клиента
3. перекидывание денег с сервака биллинга мне на кош.
Написано данное чудо просто от балды. От большого нехер делать и может быть кому-то полезно. Жду реакции и критики кода. А так же желающих доработать данное творчество.