Skip to content
This repository has been archived by the owner on May 16, 2019. It is now read-only.

Sort outpoints when releasing funds from moderator #428

Merged
merged 5 commits into from
Jun 21, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions api/restapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -1119,7 +1119,8 @@ def get_sales(self, request):
"thumbnail_hash": sale[6],
"buyer": sale[7],
"contract_type": sale[8],
"unread": sale[9]
"unread": sale[9],
"status_changed": False if sale[10] == 0 else True
}
sales_list.append(sale_json)
request.setHeader('content-type', "application/json")
Expand All @@ -1143,7 +1144,8 @@ def get_purchases(self, request):
"thumbnail_hash": purchase[6],
"vendor": purchase[7],
"contract_type": purchase[8],
"unread": purchase[9]
"unread": purchase[9],
"status_changed": False if purchase[10] == 0 else True
}
purchases_list.append(purchase_json)
request.setHeader('content-type', "application/json")
Expand Down Expand Up @@ -1181,23 +1183,30 @@ def get_order(self, request):
if os.path.exists(os.path.join(DATA_FOLDER, "purchases", "unfunded", filename)):
file_path = os.path.join(DATA_FOLDER, "purchases", "unfunded", filename)
status = self.db.purchases.get_status(request.args["order_id"][0])
self.db.purchases.status_changed(request.args["order_id"][0], 0)
elif os.path.exists(os.path.join(DATA_FOLDER, "purchases", "in progress", filename)):
file_path = os.path.join(DATA_FOLDER, "purchases", "in progress", filename)
status = self.db.purchases.get_status(request.args["order_id"][0])
self.db.purchases.status_changed(request.args["order_id"][0], 0)
elif os.path.exists(os.path.join(DATA_FOLDER, "purchases", "trade receipts", filename)):
file_path = os.path.join(DATA_FOLDER, "purchases", "trade receipts", filename)
status = self.db.purchases.get_status(request.args["order_id"][0])
self.db.purchases.status_changed(request.args["order_id"][0], 0)
elif os.path.exists(os.path.join(DATA_FOLDER, "store", "contracts", "unfunded", filename)):
file_path = os.path.join(DATA_FOLDER, "store", "contracts", "unfunded", filename)
status = self.db.sales.get_status(request.args["order_id"][0])
self.db.sales.status_changed(request.args["order_id"][0], 0)
elif os.path.exists(os.path.join(DATA_FOLDER, "store", "contracts", "in progress", filename)):
file_path = os.path.join(DATA_FOLDER, "store", "contracts", "in progress", filename)
status = self.db.sales.get_status(request.args["order_id"][0])
self.db.sales.status_changed(request.args["order_id"][0], 0)
elif os.path.exists(os.path.join(DATA_FOLDER, "store", "contracts", "trade receipts", filename)):
file_path = os.path.join(DATA_FOLDER, "store", "contracts", "trade receipts", filename)
status = self.db.sales.get_status(request.args["order_id"][0])
self.db.sales.status_changed(request.args["order_id"][0], 0)
elif os.path.exists(os.path.join(DATA_FOLDER, "cases", filename)):
file_path = os.path.join(DATA_FOLDER, "cases", filename)
self.db.cases.status_changed(request.args["order_id"][0], 0)
status = 4
else:
request.write(json.dumps({}, indent=4))
Expand Down Expand Up @@ -1325,7 +1334,8 @@ def get_cases(self, request):
"vendor": case[7],
"validation": json.loads(case[8]),
"status": "closed" if case[10] == 1 else "open",
"unread": case[11]
"unread": case[11],
"status_changed": False if case[12] == 0 else True
}
cases_list.append(purchase_json)
request.setHeader('content-type', "application/json")
Expand Down
43 changes: 35 additions & 8 deletions db/datastore.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from protos import objects
from protos.objects import Listings, Followers, Following
from os.path import join
from db.migrations import migration1, migration2, migration3, migration4, migration5
from db.migrations import migration1, migration2, migration3, migration4, migration5, migration6


class Database(object):
Expand Down Expand Up @@ -116,7 +116,7 @@ def _create_database(database_path):
conn = lite.connect(database_path)
cursor = conn.cursor()

cursor.execute('''PRAGMA user_version = 5''')
cursor.execute('''PRAGMA user_version = 6''')
cursor.execute('''CREATE TABLE hashmap(hash TEXT PRIMARY KEY, filepath TEXT)''')

cursor.execute('''CREATE TABLE profile(id INTEGER PRIMARY KEY, serializedUserInfo BLOB, tempHandle TEXT)''')
Expand Down Expand Up @@ -152,15 +152,15 @@ def _create_database(database_path):

cursor.execute('''CREATE TABLE purchases(id TEXT PRIMARY KEY, title TEXT, description TEXT,
timestamp INTEGER, btc FLOAT, address TEXT, status INTEGER, outpoint BLOB, thumbnail BLOB, vendor TEXT,
proofSig BLOB, contractType TEXT, unread INTEGER)''')
proofSig BLOB, contractType TEXT, unread INTEGER, statusChanged INTEGER)''')

cursor.execute('''CREATE TABLE sales(id TEXT PRIMARY KEY, title TEXT, description TEXT,
timestamp INTEGER, btc REAL, address TEXT, status INTEGER, thumbnail BLOB, outpoint BLOB, buyer TEXT,
paymentTX TEXT, contractType TEXT, unread INTEGER)''')
paymentTX TEXT, contractType TEXT, unread INTEGER, statusChanged INTEGER)''')

cursor.execute('''CREATE TABLE cases(id TEXT PRIMARY KEY, title TEXT, timestamp INTEGER, orderDate TEXT,
btc REAL, thumbnail BLOB, buyer TEXT, vendor TEXT, validation TEXT, claim TEXT, status INTEGER,
unread INTEGER)''')
unread INTEGER, statusChanged INTEGER)''')

cursor.execute('''CREATE TABLE ratings(listing TEXT, ratingID TEXT, rating TEXT)''')
cursor.execute('''CREATE INDEX index_listing ON ratings(listing);''')
Expand Down Expand Up @@ -204,6 +204,9 @@ def _run_migrations(self):
migration5.migrate(self.PATH)
elif version == 4:
migration5.migrate(self.PATH)
migration6.migrate(self.PATH)
elif version == 5:
migration6.migrate(self.PATH)


class HashMap(object):
Expand Down Expand Up @@ -927,7 +930,7 @@ def get_all(self):
conn = Database.connect_database(self.PATH)
cursor = conn.cursor()
cursor.execute('''SELECT id, title, description, timestamp, btc, status,
thumbnail, vendor, contractType, unread FROM purchases ''')
thumbnail, vendor, contractType, unread, statusChanged FROM purchases ''')
ret = cursor.fetchall()
conn.close()
return ret
Expand All @@ -948,6 +951,14 @@ def update_status(self, order_id, status):
conn.commit()
conn.close()

def status_changed(self, order_id, status):
conn = Database.connect_database(self.PATH)
with conn:
cursor = conn.cursor()
cursor.execute('''UPDATE purchases SET statusChanged=? WHERE id=?;''', (status, order_id))
conn.commit()
conn.close()

def get_status(self, order_id):
conn = Database.connect_database(self.PATH)
cursor = conn.cursor()
Expand Down Expand Up @@ -1048,7 +1059,7 @@ def get_all(self):
conn = Database.connect_database(self.PATH)
cursor = conn.cursor()
cursor.execute('''SELECT id, title, description, timestamp, btc, status,
thumbnail, buyer, contractType, unread FROM sales ''')
thumbnail, buyer, contractType, unread, statusChanged FROM sales ''')
ret = cursor.fetchall()
conn.close()
return ret
Expand All @@ -1069,6 +1080,14 @@ def update_status(self, order_id, status):
conn.commit()
conn.close()

def status_changed(self, order_id, status):
conn = Database.connect_database(self.PATH)
with conn:
cursor = conn.cursor()
cursor.execute('''UPDATE sales SET statusChanged=? WHERE id=?;''', (status, order_id))
conn.commit()
conn.close()

def get_status(self, order_id):
conn = Database.connect_database(self.PATH)
cursor = conn.cursor()
Expand Down Expand Up @@ -1154,7 +1173,7 @@ def get_all(self):
conn = Database.connect_database(self.PATH)
cursor = conn.cursor()
cursor.execute('''SELECT id, title, timestamp, orderDate, btc, thumbnail,
buyer, vendor, validation, claim, status, unread FROM cases ''')
buyer, vendor, validation, claim, status, unread, statusChanged FROM cases ''')
ret = cursor.fetchall()
conn.close()
return ret
Expand Down Expand Up @@ -1189,6 +1208,14 @@ def update_status(self, order_id, status):
conn.commit()
conn.close()

def status_changed(self, order_id, status):
conn = Database.connect_database(self.PATH)
with conn:
cursor = conn.cursor()
cursor.execute('''UPDATE cases SET statusChanged=? WHERE id=?;''', (status, order_id))
conn.commit()
conn.close()


class Ratings(object):
"""
Expand Down
1 change: 0 additions & 1 deletion db/migrations/migration5.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import sqlite3


def migrate(database_path):
print "migrating to db version 5"
conn = sqlite3.connect(database_path)
Expand Down
21 changes: 21 additions & 0 deletions db/migrations/migration6.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import sqlite3


def migrate(database_path):
print "migrating to db version 6"
conn = sqlite3.connect(database_path)
conn.text_factory = str
cursor = conn.cursor()

cursor.execute('''ALTER TABLE sales ADD COLUMN "statusChanged" INTEGER''')
cursor.execute('''ALTER TABLE purchases ADD COLUMN "statusChanged" INTEGER''')
cursor.execute('''ALTER TABLE cases ADD COLUMN "statusChanged" INTEGER''')

cursor.execute('''UPDATE purchases SET statusChanged = 0;''')
cursor.execute('''UPDATE purchases SET statusChanged = 0;''')
cursor.execute('''UPDATE purchases SET statusChanged = 0;''')

# update version
cursor.execute('''PRAGMA user_version = 6''')
conn.commit()
conn.close()
4 changes: 4 additions & 0 deletions market/contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@ def accept_order_confirmation(self, notification_listener, confirmation_json=Non

# update the order status in the db
self.db.purchases.update_status(contract_hash, 2)
self.db.purchases.status_changed(contract_hash, 1)
file_path = os.path.join(DATA_FOLDER, "purchases", "in progress", contract_hash + ".json")

# update the contract in the file system
Expand Down Expand Up @@ -769,6 +770,7 @@ def accept_receipt(self, notification_listener, blockchain, receipt_json=None):
json.dumps(self.contract["buyer_receipt"]["receipt"]["rating"], indent=4))

if status == 2:
self.db.sales.status_changed(order_id, 1)
self.db.sales.update_status(order_id, 3)
file_path = os.path.join(DATA_FOLDER, "store", "contracts", "trade receipts", order_id + ".json")
with open(file_path, 'w') as outfile:
Expand Down Expand Up @@ -933,6 +935,7 @@ def payment_received(self):
% order_id)

self.db.sales.update_status(order_id, 1)
self.db.sales.status_changed(order_id, 1)
self.db.sales.update_outpoint(order_id, json.dumps(self.outpoints))
self.log.info("Received new order %s" % order_id)

Expand Down Expand Up @@ -1103,6 +1106,7 @@ def process_refund(self, refund_json, blockchain, notification_listener):
self.log.info("broadcasting refund tx %s to network" % tx.get_hash())

self.db.purchases.update_status(order_id, 7)
self.db.purchases.status_changed(order_id, 1)
file_path = os.path.join(DATA_FOLDER, "purchases", "trade receipts", order_id + ".json")
with open(file_path, 'w') as outfile:
outfile.write(json.dumps(self.contract, indent=4))
Expand Down
4 changes: 4 additions & 0 deletions market/moderation.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,11 @@ def process_dispute(contract, db, message_listener, notification_listener, testn
p.avatar_hash = unhexlify(str(contract["dispute"]["info"]["avatar_hash"]))

if db.purchases.get_purchase(order_id) is not None:
db.purchases.status_changed(order_id, 1)
db.purchases.update_status(order_id, 4)

elif db.sales.get_sale(order_id) is not None:
db.sales.status_changed(order_id, 1)
db.sales.update_status(order_id, 4)

elif "moderators" in contract["vendor_offer"]["listing"]:
Expand Down Expand Up @@ -175,9 +177,11 @@ def close_dispute(resolution_json, db, message_listener, notification_listener,
contract["dispute_resolution"] = resolution_json["dispute_resolution"]

if db.purchases.get_purchase(order_id) is not None:
db.purchases.status_changed(order_id, 1)
db.purchases.update_status(order_id, 5)

elif db.sales.get_sale(order_id) is not None:
db.sales.status_changed(order_id, 1)
db.sales.update_status(order_id, 5)

with open(file_path, 'wb') as outfile:
Expand Down
13 changes: 13 additions & 0 deletions market/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
import os.path
import pickle
import time
import struct
from binascii import unhexlify
from bitcoin.core import b2lx
from collections import OrderedDict
from config import DATA_FOLDER, TRANSACTION_FEE
from dht.node import Node
Expand Down Expand Up @@ -953,6 +955,7 @@ def release_funds(self, order_id):
This function should be called to release funds from a disputed contract after
the moderator has resolved the dispute and provided his signature.
"""

if os.path.exists(os.path.join(DATA_FOLDER, "purchases", "in progress", order_id + ".json")):
file_path = os.path.join(DATA_FOLDER, "purchases", "in progress", order_id + ".json")
outpoints = json.loads(self.db.purchases.get_outpoint(order_id))
Expand Down Expand Up @@ -983,6 +986,16 @@ def release_funds(self, order_id):
["resolution"]["vendor_payout"]) * 100000000)),
'address': vendor_address})

# version 0.2.1 and above ensure same sort order as moderator.
o = []
for s in contract["dispute_resolution"]["resolution"]["tx_signatures"]:
if "outpoint" in s:
for outpoint in outpoints:
ser = outpoint["txid"] + b2lx(struct.pack(b"<I", outpoint["vout"]))
if ser == s["outpoint"]:
o.append(outpoint)
if len(o) != 0:
outpoints = o
tx = BitcoinTransaction.make_unsigned(outpoints, outputs, testnet=self.protocol.multiplexer.testnet)
chaincode = contract["buyer_order"]["order"]["payment"]["chaincode"]
redeem_script = str(contract["buyer_order"]["order"]["payment"]["redeem_script"])
Expand Down
3 changes: 2 additions & 1 deletion market/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ def create_signature(self, privkey, reedem_script):
sighash = SignatureHash(CScript(x(reedem_script)), self.tx, i, SIGHASH_ALL)
signatures.append({
"index": i,
"signature": (seckey.sign(sighash) + struct.pack('<B', SIGHASH_ALL)).encode("hex")
"signature": (seckey.sign(sighash) + struct.pack('<B', SIGHASH_ALL)).encode("hex"),
"outpoint": b2lx(self.tx.vin[i].prevout.hash) + b2lx(struct.pack(b"<I", self.tx.vin[i].prevout.n))
})
return signatures

Expand Down
5 changes: 3 additions & 2 deletions openbazaard.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
from twisted.python import log, logfile
from txws import WebSocketFactory


def run(*args):
TESTNET = args[0]
LOGLEVEL = args[1]
Expand Down Expand Up @@ -213,7 +214,7 @@ class Parser(object):
def __init__(self, daemon):
self.daemon = daemon
parser = argparse.ArgumentParser(
description='OpenBazaar-Server v0.2.0',
description='OpenBazaar-Server v0.2.1',
usage='''
python openbazaard.py <command> [<args>]
python openbazaard.py <command> --help
Expand Down Expand Up @@ -302,6 +303,6 @@ def print_splash_screen():
print "\_______ / __/ \___ >___| /" + OKBLUE + "______ /(____ /_____ \(____ (____ /__|" + ENDC
print " \/|__| \/ \/ " + OKBLUE + " \/ \/ \/ \/ \/" + ENDC
print
print "OpenBazaar Server v0.1 starting..."
print "OpenBazaar Server v0.2.1 starting..."

Parser(OpenBazaard('/tmp/openbazaard.pid'))