Merge branch 'master' of github.com:zcash-hackworks/ZBXCAT
This commit is contained in:
commit
9f01f7fc30
|
@ -67,8 +67,6 @@ class bitcoinProxy():
|
||||||
def get_keys(self, funder_address, redeemer_address):
|
def get_keys(self, funder_address, redeemer_address):
|
||||||
fundpubkey = CBitcoinAddress(funder_address)
|
fundpubkey = CBitcoinAddress(funder_address)
|
||||||
redeempubkey = CBitcoinAddress(redeemer_address)
|
redeempubkey = CBitcoinAddress(redeemer_address)
|
||||||
# fundpubkey = self.bitcoind.getnewaddress()
|
|
||||||
# redeempubkey = self.bitcoind.getnewaddress()
|
|
||||||
return fundpubkey, redeempubkey
|
return fundpubkey, redeempubkey
|
||||||
|
|
||||||
def privkey(self, address):
|
def privkey(self, address):
|
||||||
|
@ -79,7 +77,8 @@ class bitcoinProxy():
|
||||||
redeemerAddr = CBitcoinAddress(redeemer)
|
redeemerAddr = CBitcoinAddress(redeemer)
|
||||||
if type(commitment) == str:
|
if type(commitment) == str:
|
||||||
commitment = x(commitment)
|
commitment = x(commitment)
|
||||||
# h = sha256(secret)
|
else:
|
||||||
|
raise ValueError("Commitment was not a string: {0}".format(commitment))
|
||||||
blocknum = self.bitcoind.getblockcount()
|
blocknum = self.bitcoind.getblockcount()
|
||||||
print("Current blocknum on Bitcoin: ", blocknum)
|
print("Current blocknum on Bitcoin: ", blocknum)
|
||||||
redeemblocknum = blocknum + locktime
|
redeemblocknum = blocknum + locktime
|
||||||
|
|
202
xcat/cli.py
202
xcat/cli.py
|
@ -9,43 +9,38 @@ import xcat.utils as utils
|
||||||
from xcat.protocol import Protocol
|
from xcat.protocol import Protocol
|
||||||
from xcat.trades import Trade
|
from xcat.trades import Trade
|
||||||
|
|
||||||
|
class CLI():
|
||||||
|
def __init__(self):
|
||||||
|
self.db = DB()
|
||||||
|
self.protocol = Protocol()
|
||||||
|
|
||||||
def save_state(trade, tradeid):
|
def checkSellStatus(self, tradeid):
|
||||||
db = DB()
|
trade = self.db.get(tradeid)
|
||||||
utils.save(trade)
|
status = self.seller_check_status(trade)
|
||||||
db.create(trade, tradeid)
|
|
||||||
|
|
||||||
|
|
||||||
def checkSellStatus(tradeid):
|
|
||||||
db = DB()
|
|
||||||
protocol = Protocol()
|
|
||||||
|
|
||||||
trade = db.get(tradeid)
|
|
||||||
status = seller_check_status(trade)
|
|
||||||
print("Trade status: {0}\n".format(status))
|
print("Trade status: {0}\n".format(status))
|
||||||
|
|
||||||
if status == 'init':
|
if status == 'init':
|
||||||
userInput.authorize_fund_sell(trade)
|
userInput.authorize_fund_sell(trade)
|
||||||
fund_tx = protocol.fund_sell_contract(trade)
|
fund_tx = self.protocol.fund_sell_contract(trade)
|
||||||
|
|
||||||
print("Sent fund_tx", fund_tx)
|
print("Sent fund_tx", fund_tx)
|
||||||
trade.sell.fund_tx = fund_tx
|
trade.sell.fund_tx = fund_tx
|
||||||
save_state(trade, tradeid)
|
self.db.create(trade, tradeid)
|
||||||
|
|
||||||
elif status == 'buyerFunded':
|
elif status == 'buyerFunded':
|
||||||
secret = db.get_secret(tradeid)
|
secret = self.db.get_secret(tradeid)
|
||||||
print("Retrieved secret to redeem funds for "
|
print("Retrieved secret to redeem funds for "
|
||||||
"{0}: {1}".format(tradeid, secret))
|
"{0}: {1}".format(tradeid, secret))
|
||||||
txs = protocol.seller_redeem_p2sh(trade, secret)
|
txs = self.protocol.seller_redeem_p2sh(trade, secret)
|
||||||
if 'redeem_tx' in txs:
|
if 'redeem_tx' in txs:
|
||||||
trade.buy.redeem_tx = txs['redeem_tx']
|
trade.buy.redeem_tx = txs['redeem_tx']
|
||||||
print("Redeem tx: ", txs['redeem_tx'])
|
print("Redeem tx: ", txs['redeem_tx'])
|
||||||
if 'refund_tx' in txs:
|
if 'refund_tx' in txs:
|
||||||
trade.buy.redeem_tx = txs['refund_tx']
|
trade.buy.redeem_tx = txs['refund_tx']
|
||||||
print("Buyer refund tx: ", txs['refund_tx'])
|
print("Buyer refund tx: ", txs['refund_tx'])
|
||||||
txs = protocol.refund_contract(trade.sell) # Refund to seller
|
txs = self.protocol.refund_contract(trade.sell) # Refund to seller
|
||||||
print("Your refund txid: ", txs['refund_tx'])
|
print("Your refund txid: ", txs['refund_tx'])
|
||||||
save_state(trade, tradeid)
|
self.db.create(trade, tradeid)
|
||||||
# Remove from db? Or just from temporary file storage
|
# Remove from db? Or just from temporary file storage
|
||||||
utils.cleanup(tradeid)
|
utils.cleanup(tradeid)
|
||||||
|
|
||||||
|
@ -59,11 +54,10 @@ def checkSellStatus(tradeid):
|
||||||
"this trade.")
|
"this trade.")
|
||||||
|
|
||||||
|
|
||||||
def buyer_check_status(trade):
|
def buyer_check_status(self, trade):
|
||||||
protocol = Protocol()
|
sellState = self.protocol.check_fund_status(
|
||||||
sellState = protocol.check_fund_status(
|
|
||||||
trade.sell.currency, trade.sell.p2sh)
|
trade.sell.currency, trade.sell.p2sh)
|
||||||
buyState = protocol.check_fund_status(
|
buyState = self.protocol.check_fund_status(
|
||||||
trade.buy.currency, trade.buy.p2sh)
|
trade.buy.currency, trade.buy.p2sh)
|
||||||
if sellState == 'funded' and buyState == 'empty':
|
if sellState == 'funded' and buyState == 'empty':
|
||||||
return 'sellerFunded' # step1
|
return 'sellerFunded' # step1
|
||||||
|
@ -79,11 +73,10 @@ def buyer_check_status(trade):
|
||||||
return 'init'
|
return 'init'
|
||||||
|
|
||||||
|
|
||||||
def seller_check_status(trade):
|
def seller_check_status(self, trade):
|
||||||
protocol = Protocol()
|
sellState = self.protocol.check_fund_status(
|
||||||
sellState = protocol.check_fund_status(
|
|
||||||
trade.sell.currency, trade.sell.p2sh)
|
trade.sell.currency, trade.sell.p2sh)
|
||||||
buyState = protocol.check_fund_status(
|
buyState = self.protocol.check_fund_status(
|
||||||
trade.buy.currency, trade.buy.p2sh)
|
trade.buy.currency, trade.buy.p2sh)
|
||||||
if sellState == 'funded' and buyState == 'empty':
|
if sellState == 'funded' and buyState == 'empty':
|
||||||
return 'sellerFunded' # step1
|
return 'sellerFunded' # step1
|
||||||
|
@ -99,11 +92,9 @@ def seller_check_status(trade):
|
||||||
return 'init' # step0
|
return 'init' # step0
|
||||||
|
|
||||||
|
|
||||||
def checkBuyStatus(tradeid):
|
def checkBuyStatus(self, tradeid):
|
||||||
db = DB()
|
trade = self.db.get(tradeid)
|
||||||
protocol = Protocol()
|
status = self.buyer_check_status(trade)
|
||||||
trade = db.get(tradeid)
|
|
||||||
status = buyer_check_status(trade)
|
|
||||||
print("Trade status: {0}\n".format(status))
|
print("Trade status: {0}\n".format(status))
|
||||||
if status == 'init':
|
if status == 'init':
|
||||||
print("Trade has not yet started, waiting for seller to fund the "
|
print("Trade has not yet started, waiting for seller to fund the "
|
||||||
|
@ -116,24 +107,24 @@ def checkBuyStatus(tradeid):
|
||||||
"behalf.")
|
"behalf.")
|
||||||
print("Trade commitment", trade.commitment)
|
print("Trade commitment", trade.commitment)
|
||||||
# if verify_p2sh(trade):
|
# if verify_p2sh(trade):
|
||||||
fund_tx = protocol.fund_contract(trade.buy)
|
fund_tx = self.protocol.fund_contract(trade.buy)
|
||||||
print("\nYou sent this funding tx: ", fund_tx)
|
print("\nYou sent this funding tx: ", fund_tx)
|
||||||
trade.buy.fund_tx = fund_tx
|
trade.buy.fund_tx = fund_tx
|
||||||
save_state(trade, tradeid)
|
self.db.create(trade, tradeid)
|
||||||
elif status == 'sellerRedeemed':
|
elif status == 'sellerRedeemed':
|
||||||
secret = protocol.find_secret_from_fundtx(trade.buy.currency,
|
secret = self.protocol.find_secret_from_fundtx(trade.buy.currency,
|
||||||
trade.buy.p2sh,
|
trade.buy.p2sh,
|
||||||
trade.buy.fund_tx)
|
trade.buy.fund_tx)
|
||||||
if secret is not None:
|
if secret is not None:
|
||||||
print("Found secret on blockchain in seller's redeem tx: ", secret)
|
print("Found secret on blockchain in seller's redeem tx: ", secret)
|
||||||
txs = protocol.redeem_p2sh(trade.sell, secret)
|
txs = self.protocol.redeem_p2sh(trade.sell, secret)
|
||||||
if 'redeem_tx' in txs:
|
if 'redeem_tx' in txs:
|
||||||
trade.sell.redeem_tx = txs['redeem_tx']
|
trade.sell.redeem_tx = txs['redeem_tx']
|
||||||
print("Redeem txid: ", trade.sell.redeem_tx)
|
print("Redeem txid: ", trade.sell.redeem_tx)
|
||||||
elif 'refund_tx' in txs:
|
elif 'refund_tx' in txs:
|
||||||
trade.sell.redeem_tx = txs['refund_tx']
|
trade.sell.redeem_tx = txs['refund_tx']
|
||||||
print("Refund tx: ", txs['refund_tx'])
|
print("Refund tx: ", txs['refund_tx'])
|
||||||
save_state(trade, tradeid)
|
self.db.create(trade, tradeid)
|
||||||
print("XCAT trade complete!")
|
print("XCAT trade complete!")
|
||||||
else:
|
else:
|
||||||
# Search if tx has been refunded from p2sh
|
# Search if tx has been refunded from p2sh
|
||||||
|
@ -141,23 +132,22 @@ def checkBuyStatus(tradeid):
|
||||||
|
|
||||||
|
|
||||||
# Import a trade in hex, and save to db
|
# Import a trade in hex, and save to db
|
||||||
def importtrade(tradeid, hexstr=''):
|
def importtrade(self, tradeid, hexstr=''):
|
||||||
protocol = Protocol()
|
|
||||||
trade = utils.x2s(hexstr)
|
trade = utils.x2s(hexstr)
|
||||||
trade = Trade(trade)
|
trade = Trade(trade)
|
||||||
protocol.import_addrs(trade)
|
self.protocol.import_addrs(trade)
|
||||||
print(trade.toJSON())
|
print(trade.toJSON())
|
||||||
save_state(trade, tradeid)
|
self.db.create(trade, tradeid)
|
||||||
|
|
||||||
|
|
||||||
def wormhole_importtrade():
|
def wormhole_importtrade(self):
|
||||||
res = subprocess.call('wormhole receive', shell=True)
|
res = subprocess.call('wormhole receive', shell=True)
|
||||||
if res == 0:
|
if res == 0:
|
||||||
tradeid = input("Enter filename of received trade data to import "
|
tradeid = input("Enter filename of received trade data to import "
|
||||||
"(printed on line above): ")
|
"(printed on line above): ")
|
||||||
with open(tradeid) as infile:
|
with open(tradeid) as infile:
|
||||||
hexstr = infile.readline().strip()
|
hexstr = infile.readline().strip()
|
||||||
importtrade(tradeid, hexstr)
|
self.importtrade(tradeid, hexstr)
|
||||||
print("Successfully imported trade using magic-wormhole")
|
print("Successfully imported trade using magic-wormhole")
|
||||||
os.remove(tradeid)
|
os.remove(tradeid)
|
||||||
else:
|
else:
|
||||||
|
@ -165,9 +155,8 @@ def wormhole_importtrade():
|
||||||
|
|
||||||
|
|
||||||
# Export a trade by its tradeid
|
# Export a trade by its tradeid
|
||||||
def exporttrade(tradeid, wormhole=False):
|
def exporttrade(self, tradeid, wormhole=False):
|
||||||
db = DB()
|
trade = self.db.get(tradeid)
|
||||||
trade = db.get(tradeid)
|
|
||||||
hexstr = utils.s2x(trade.toJSON())
|
hexstr = utils.s2x(trade.toJSON())
|
||||||
if wormhole:
|
if wormhole:
|
||||||
tradefile = os.path.join(utils.ROOT_DIR, '.tmp/{0}'.format(tradeid))
|
tradefile = os.path.join(utils.ROOT_DIR, '.tmp/{0}'.format(tradeid))
|
||||||
|
@ -180,81 +169,69 @@ def exporttrade(tradeid, wormhole=False):
|
||||||
print(hexstr)
|
print(hexstr)
|
||||||
return hexstr
|
return hexstr
|
||||||
|
|
||||||
|
def findtrade(self, tradeid):
|
||||||
def findtrade(tradeid):
|
trade = self.db.get(tradeid)
|
||||||
db = DB()
|
|
||||||
trade = db.get(tradeid)
|
|
||||||
print(trade.toJSON())
|
print(trade.toJSON())
|
||||||
return trade
|
return trade
|
||||||
|
|
||||||
|
def find_role(self, contract):
|
||||||
def find_role(contract):
|
|
||||||
protocol = Protocol()
|
|
||||||
# When regtest created both addrs on same machine, role is both.
|
# When regtest created both addrs on same machine, role is both.
|
||||||
if protocol.is_myaddr(contract.initiator):
|
if self.protocol.is_myaddr(contract.initiator):
|
||||||
if protocol.is_myaddr(contract.fulfiller):
|
if self.protocol.is_myaddr(contract.fulfiller):
|
||||||
return 'test'
|
return 'test'
|
||||||
else:
|
else:
|
||||||
return 'initiator'
|
return 'initiator'
|
||||||
else:
|
else:
|
||||||
if protocol.is_myaddr(contract.fulfiller):
|
if self.protocol.is_myaddr(contract.fulfiller):
|
||||||
return 'fulfiller'
|
return 'fulfiller'
|
||||||
else:
|
else:
|
||||||
raise ValueError('You are not a participant in this contract.')
|
raise ValueError('You are not a participant in this contract.')
|
||||||
|
|
||||||
|
|
||||||
def checktrade(tradeid):
|
def checktrade(self, tradeid):
|
||||||
db = DB()
|
|
||||||
print("In checktrade")
|
print("In checktrade")
|
||||||
trade = db.get(tradeid)
|
trade = self.db.get(tradeid)
|
||||||
if find_role(trade.sell) == 'test':
|
if find_role(trade.sell) == 'test':
|
||||||
input("Is this a test? Both buyer and seller addresses are yours, "
|
input("Is this a test? Both buyer and seller addresses are yours, "
|
||||||
"press 'enter' to test.")
|
"press 'enter' to test.")
|
||||||
checkSellStatus(tradeid)
|
self.checkSellStatus(tradeid)
|
||||||
checkBuyStatus(tradeid)
|
self.checkBuyStatus(tradeid)
|
||||||
checkSellStatus(tradeid)
|
self.checkSellStatus(tradeid)
|
||||||
checkBuyStatus(tradeid)
|
self.checkBuyStatus(tradeid)
|
||||||
elif find_role(trade.sell) == 'initiator':
|
elif find_role(trade.sell) == 'initiator':
|
||||||
print("You are the seller in this trade.")
|
print("You are the seller in this trade.")
|
||||||
# role = 'seller'
|
# role = 'seller'
|
||||||
checkSellStatus(tradeid)
|
self.checkSellStatus(tradeid)
|
||||||
else:
|
else:
|
||||||
print("You are the buyer in this trade.")
|
print("You are the buyer in this trade.")
|
||||||
# role = 'buyer'
|
# role = 'buyer'
|
||||||
checkBuyStatus(tradeid)
|
self.checkBuyStatus(tradeid)
|
||||||
|
|
||||||
|
def newtrade(self, tradeid, **kwargs):
|
||||||
def newtrade(tradeid, **kwargs):
|
|
||||||
protocol = Protocol()
|
|
||||||
print("Creating new XCAT trade...")
|
print("Creating new XCAT trade...")
|
||||||
utils.erase_trade()
|
utils.erase_trade()
|
||||||
|
|
||||||
conf = kwargs['conf'] if 'conf' in kwargs else 'regtest'
|
conf = kwargs['conf'] if 'conf' in kwargs else 'regtest'
|
||||||
network = kwargs['network'] if 'network' in kwargs else 'regtest'
|
network = kwargs['network'] if 'network' in kwargs else 'regtest'
|
||||||
|
tradeid, trade = self.protocol.initialize_trade(tradeid, conf=conf, network=network)
|
||||||
tradeid, trade = protocol.initialize_trade(
|
|
||||||
tradeid,
|
|
||||||
conf=conf,
|
|
||||||
network=network)
|
|
||||||
print("New trade created: {0}".format(trade))
|
print("New trade created: {0}".format(trade))
|
||||||
|
|
||||||
trade = protocol.seller_init(tradeid, trade, network=network)
|
trade, secret = self.protocol.seller_init(tradeid, trade, network=network)
|
||||||
print("\nUse 'xcat exporttrade [tradeid]' to export the trade and sent "
|
self.db.save_secret(tradeid, secret)
|
||||||
"to the buyer.\n")
|
print("\nGenerated a secret preimage to lock funds. This will only "
|
||||||
|
"be stored locally: {0}".format(secret))
|
||||||
|
print("\nUse 'xcat exporttrade [tradeid]' to export the trade and send to the buyer.\n")
|
||||||
|
|
||||||
save_state(trade, tradeid)
|
self.db.create(trade, tradeid)
|
||||||
return trade
|
return trade
|
||||||
|
|
||||||
|
def listtrades(self):
|
||||||
def listtrades():
|
|
||||||
db = DB()
|
|
||||||
print("Trades")
|
print("Trades")
|
||||||
trade_list = db.dump()
|
trade_list = self.db.dump()
|
||||||
for trade in trade_list:
|
for trade in trade_list:
|
||||||
print("{0}: {1}".format(trade[0], trade[1]))
|
print("{0}: {1}".format(trade[0], trade[1]))
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
cli = CLI()
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
formatter_class=argparse.RawTextHelpFormatter,
|
formatter_class=argparse.RawTextHelpFormatter,
|
||||||
description=textwrap.dedent('''\
|
description=textwrap.dedent('''\
|
||||||
|
@ -266,26 +243,15 @@ def main():
|
||||||
findtrade "tradeid" - find a trade by the tradeid
|
findtrade "tradeid" - find a trade by the tradeid
|
||||||
|
|
||||||
'''))
|
'''))
|
||||||
|
parser.add_argument("command", action="store", help="list commands")
|
||||||
parser.add_argument(
|
parser.add_argument("arguments", action="store", nargs="*", help="add arguments")
|
||||||
"command", action="store", help="list commands")
|
parser.add_argument("-d", "--debug", action="store_true", help="Enable debug mode. Defaults to false")
|
||||||
parser.add_argument(
|
parser.add_argument("-w", "--wormhole", action="store_true", help="Transfer trade data through magic-wormhole")
|
||||||
"arguments", action="store", nargs="*", help="add arguments")
|
parser.add_argument("-c", "--conf", action="store", help="Use trade data in conf file ('testnet' or 'regtest'), or pass trade data in on cli as json.")
|
||||||
parser.add_argument(
|
parser.add_argument("-n", "--network", action="store", help="Set network to regtest or mainnet. Defaults to testnet while in alpha.")
|
||||||
"-w", "--wormhole", action="store_true",
|
# parser.add_argument("--daemon", "-d", action="store_true", help="Run as daemon process")
|
||||||
help="Transfer trade data through magic-wormhole")
|
|
||||||
parser.add_argument(
|
|
||||||
"-c", "--conf", action="store",
|
|
||||||
help="Use default trade data in conf file.")
|
|
||||||
parser.add_argument(
|
|
||||||
"-n", "--network", action="store",
|
|
||||||
help=("Set network to regtest or mainnet. "
|
|
||||||
"Defaults to testnet while in alpha."))
|
|
||||||
# parser.add_argument(
|
|
||||||
# "--daemon", "-d", action="store_true",
|
|
||||||
# help="Run as daemon process")
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
print(args)
|
||||||
|
|
||||||
if hasattr(args, 'debug'):
|
if hasattr(args, 'debug'):
|
||||||
numeric_level = getattr(logging, 'DEBUG', None)
|
numeric_level = getattr(logging, 'DEBUG', None)
|
||||||
|
@ -304,35 +270,35 @@ def main():
|
||||||
|
|
||||||
if command == 'importtrade':
|
if command == 'importtrade':
|
||||||
if args.wormhole:
|
if args.wormhole:
|
||||||
wormhole_importtrade()
|
cli.wormhole_importtrade()
|
||||||
else:
|
else:
|
||||||
if len(args.arguments) != 2:
|
if len(args.arguments) != 2:
|
||||||
utils.throw("Usage: importtrade [tradeid] [hexstring]")
|
utils.throw("Usage: importtrade [tradeid] [hexstring]")
|
||||||
tradeid = args.arguments[0]
|
tradeid = args.arguments[0]
|
||||||
hexstr = args.arguments[1]
|
hexstr = args.arguments[1]
|
||||||
importtrade(tradeid, hexstr)
|
cli.importtrade(tradeid, hexstr)
|
||||||
|
|
||||||
elif command == 'exporttrade':
|
elif command == 'exporttrade':
|
||||||
if len(args.arguments) < 1:
|
if len(args.arguments) < 1:
|
||||||
utils.throw("Usage: exporttrade [tradeid]")
|
utils.throw("Usage: exporttrade [tradeid]")
|
||||||
tradeid = args.arguments[0]
|
tradeid = args.arguments[0]
|
||||||
exporttrade(tradeid, args.wormhole)
|
cli.exporttrade(tradeid, args.wormhole)
|
||||||
|
|
||||||
elif command == "findtrade":
|
elif command == "findtrade":
|
||||||
if len(args.arguments) < 1:
|
if len(args.arguments) < 1:
|
||||||
utils.throw("Usage: findtrade [tradeid]")
|
utils.throw("Usage: findtrade [tradeid]")
|
||||||
print("Finding trade")
|
print("Finding trade")
|
||||||
key = args.arguments[0]
|
key = args.arguments[0]
|
||||||
findtrade(key)
|
cli.findtrade(key)
|
||||||
|
|
||||||
elif command == 'checktrade':
|
elif command == 'checktrade':
|
||||||
if len(args.arguments) < 1:
|
if len(args.arguments) < 1:
|
||||||
utils.throw("Usage: checktrade [tradeid]")
|
utils.throw("Usage: checktrade [tradeid]")
|
||||||
tradeid = args.arguments[0]
|
tradeid = args.arguments[0]
|
||||||
checktrade(tradeid)
|
cli.checktrade(tradeid)
|
||||||
|
|
||||||
elif command == 'listtrades':
|
elif command == 'listtrades':
|
||||||
listtrades()
|
cli.listtrades()
|
||||||
|
|
||||||
# TODO: function to tell if tradeid already exists for newtrade
|
# TODO: function to tell if tradeid already exists for newtrade
|
||||||
|
|
||||||
|
@ -341,31 +307,27 @@ def main():
|
||||||
utils.throw("Usage: newtrade [tradeid]")
|
utils.throw("Usage: newtrade [tradeid]")
|
||||||
tradeid = args.arguments[0]
|
tradeid = args.arguments[0]
|
||||||
if args.conf is None:
|
if args.conf is None:
|
||||||
newtrade(tradeid, network=NETWORK, conf='cli')
|
conf = 'cli'
|
||||||
else:
|
else:
|
||||||
newtrade(tradeid, network=NETWORK, conf=args.conf)
|
conf = args.conf
|
||||||
|
cli.newtrade(tradeid, network=NETWORK, conf=conf)
|
||||||
|
|
||||||
elif command == "daemon":
|
elif command == "daemon":
|
||||||
# TODO: not implemented
|
# TODO: not implemented
|
||||||
print("Run as daemon process")
|
print("Run as daemon process")
|
||||||
|
|
||||||
# Ad hoc testing of workflow starts here
|
# Ad hoc testing of workflow starts here
|
||||||
|
|
||||||
elif command == "step1":
|
elif command == "step1":
|
||||||
tradeid = args.arguments[0]
|
tradeid = args.arguments[0]
|
||||||
checkSellStatus(tradeid)
|
cli.checkSellStatus(tradeid)
|
||||||
|
|
||||||
elif command == "step2":
|
elif command == "step2":
|
||||||
tradeid = args.arguments[0]
|
tradeid = args.arguments[0]
|
||||||
checkBuyStatus(tradeid)
|
cli.checkBuyStatus(tradeid)
|
||||||
|
|
||||||
elif command == "step3":
|
elif command == "step3":
|
||||||
# protocol = Protocol()
|
# cli.protocol.generate(31)
|
||||||
# protocol.generate(31)
|
|
||||||
tradeid = args.arguments[0]
|
tradeid = args.arguments[0]
|
||||||
checkSellStatus(tradeid)
|
cli.checkSellStatus(tradeid)
|
||||||
|
|
||||||
elif command == "step4":
|
elif command == "step4":
|
||||||
# generate(1)
|
# cli.protocol.generate(1)
|
||||||
tradeid = args.arguments[0]
|
tradeid = args.arguments[0]
|
||||||
checkBuyStatus(tradeid)
|
cli.checkBuyStatus(tradeid)
|
||||||
|
|
|
@ -5,11 +5,9 @@ from xcat.xcatconf import ADDRS
|
||||||
from xcat.trades import Contract, Trade
|
from xcat.trades import Contract, Trade
|
||||||
from xcat.bitcoinRPC import bitcoinProxy
|
from xcat.bitcoinRPC import bitcoinProxy
|
||||||
from xcat.zcashRPC import zcashProxy
|
from xcat.zcashRPC import zcashProxy
|
||||||
from xcat.db import DB
|
import json
|
||||||
|
|
||||||
|
|
||||||
class Protocol():
|
class Protocol():
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.bitcoinRPC = bitcoinProxy()
|
self.bitcoinRPC = bitcoinProxy()
|
||||||
self.zcashRPC = zcashProxy()
|
self.zcashRPC = zcashProxy()
|
||||||
|
@ -186,6 +184,22 @@ class Protocol():
|
||||||
"{0} {1}!".format(buy.amount, buy.currency))
|
"{0} {1}!".format(buy.amount, buy.currency))
|
||||||
return txs
|
return txs
|
||||||
|
|
||||||
|
def seller_init(self, tradeid, trade, network):
|
||||||
|
secret = utils.generate_password()
|
||||||
|
hash_of_secret = utils.sha256(secret)
|
||||||
|
# TODO: Implement locktimes and mock block passage of time
|
||||||
|
sell_locktime = 20
|
||||||
|
buy_locktime = 10 # Must be more than first tx
|
||||||
|
print("Creating pay-to-script-hash for sell contract...")
|
||||||
|
|
||||||
|
# create the p2sh addrs
|
||||||
|
self.create_sell_p2sh(trade, hash_of_secret, sell_locktime)
|
||||||
|
self.create_buy_p2sh(trade, hash_of_secret, buy_locktime)
|
||||||
|
|
||||||
|
trade.commitment = utils.b2x(hash_of_secret)
|
||||||
|
print("TRADE after seller init {0}".format(trade.toJSON()))
|
||||||
|
return trade, secret
|
||||||
|
|
||||||
def initialize_trade(self, tradeid, **kwargs):
|
def initialize_trade(self, tradeid, **kwargs):
|
||||||
trade = Trade()
|
trade = Trade()
|
||||||
conf = kwargs['conf']
|
conf = kwargs['conf']
|
||||||
|
@ -195,9 +209,16 @@ class Protocol():
|
||||||
amounts = userInput.get_trade_amounts()
|
amounts = userInput.get_trade_amounts()
|
||||||
print("AMOUNTS", amounts)
|
print("AMOUNTS", amounts)
|
||||||
else:
|
else:
|
||||||
init_addrs = ADDRS[conf]['initiator']
|
print("Conf in init trade", conf)
|
||||||
fulfill_addrs = ADDRS[conf]['fulfiller']
|
if conf == 'testnet' or conf == 'regtest':
|
||||||
amounts = ADDRS[conf]['amounts']
|
# If json is not passed on cli, use ADDR obj from xcatconf.py
|
||||||
|
conf = ADDRS[conf]
|
||||||
|
else:
|
||||||
|
# Allow for passing in multiple trades at a time
|
||||||
|
conf = json.loads(conf)[0]
|
||||||
|
init_addrs = conf['initiator']
|
||||||
|
fulfill_addrs = conf['fulfiller']
|
||||||
|
amounts = conf['amounts']
|
||||||
|
|
||||||
sell = amounts['sell']
|
sell = amounts['sell']
|
||||||
buy = amounts['buy']
|
buy = amounts['buy']
|
||||||
|
@ -214,24 +235,3 @@ class Protocol():
|
||||||
print(trade.sell.__dict__)
|
print(trade.sell.__dict__)
|
||||||
print(trade.buy.__dict__)
|
print(trade.buy.__dict__)
|
||||||
return tradeid, trade
|
return tradeid, trade
|
||||||
|
|
||||||
def seller_init(self, tradeid, trade, network):
|
|
||||||
db = DB()
|
|
||||||
secret = utils.generate_password()
|
|
||||||
db.save_secret(tradeid, secret)
|
|
||||||
print("\nGenerated a secret preimage to lock funds. This will only "
|
|
||||||
"be stored locally: {0}".format(secret))
|
|
||||||
|
|
||||||
hash_of_secret = utils.sha256(secret)
|
|
||||||
# TODO: Implement locktimes and mock block passage of time
|
|
||||||
sell_locktime = 20
|
|
||||||
buy_locktime = 10 # Must be more than first tx
|
|
||||||
print("Creating pay-to-script-hash for sell contract...")
|
|
||||||
|
|
||||||
# create the p2sh addrs
|
|
||||||
self.create_sell_p2sh(trade, hash_of_secret, sell_locktime)
|
|
||||||
self.create_buy_p2sh(trade, hash_of_secret, buy_locktime)
|
|
||||||
|
|
||||||
trade.commitment = utils.b2x(hash_of_secret)
|
|
||||||
print("TRADE after seller init {0}".format(trade.toJSON()))
|
|
||||||
return trade
|
|
||||||
|
|
|
@ -1,103 +0,0 @@
|
||||||
import xcat.zcash
|
|
||||||
import xcat.bitcoin
|
|
||||||
from xcat import *
|
|
||||||
|
|
||||||
htlcTrade = Trade()
|
|
||||||
print("Starting test of xcat...")
|
|
||||||
|
|
||||||
def get_initiator_addresses():
|
|
||||||
return {'bitcoin': 'myfFr5twPYNwgeXyjCmGcrzXtCmfmWXKYp', 'zcash': 'tmFRXyju7ANM7A9mg75ZjyhFW1UJEhUPwfQ'}
|
|
||||||
|
|
||||||
def get_fulfiller_addresses():
|
|
||||||
return {'bitcoin': 'mrQzUGU1dwsWRx5gsKKSDPNtrsP65vCA3Z', 'zcash': 'tmTjZSg4pX2Us6V5HttiwFZwj464fD2ZgpY'}
|
|
||||||
|
|
||||||
def initiate(trade):
|
|
||||||
# Get amounts
|
|
||||||
amounts = {"sell": {"currency": "bitcoin", "amount": "0.5"}, "buy": {"currency": "zcash", "amount": "1.12"}}
|
|
||||||
sell = amounts['sell']
|
|
||||||
buy = amounts['buy']
|
|
||||||
sell_currency = sell['currency']
|
|
||||||
buy_currency = buy['currency']
|
|
||||||
# Get addresses
|
|
||||||
init_addrs = get_initiator_addresses()
|
|
||||||
sell['initiator'] = init_addrs[sell_currency]
|
|
||||||
buy['initiator'] = init_addrs[buy_currency]
|
|
||||||
fulfill_addrs = get_fulfiller_addresses()
|
|
||||||
sell['fulfiller'] = fulfill_addrs[sell_currency]
|
|
||||||
buy['fulfiller'] = fulfill_addrs[buy_currency]
|
|
||||||
# initializing contract classes with addresses, currencies, and amounts
|
|
||||||
trade.sell = Contract(sell)
|
|
||||||
trade.buy = Contract(buy)
|
|
||||||
print(trade.sell.__dict__)
|
|
||||||
print(trade.buy.__dict__)
|
|
||||||
|
|
||||||
secret = generate_password()
|
|
||||||
print("Generating secret to lock funds:", secret)
|
|
||||||
save_secret(secret)
|
|
||||||
# TODO: Implement locktimes and mock block passage of time
|
|
||||||
sell_locktime = 2
|
|
||||||
buy_locktime = 4 # Must be more than first tx
|
|
||||||
|
|
||||||
create_sell_p2sh(trade, secret, sell_locktime)
|
|
||||||
txid = fund_sell_contract(trade)
|
|
||||||
print("Sent")
|
|
||||||
create_buy_p2sh(trade, secret, buy_locktime)
|
|
||||||
|
|
||||||
def fulfill(trade):
|
|
||||||
buy = trade.buy
|
|
||||||
sell = trade.sell
|
|
||||||
buy_p2sh_balance = check_p2sh(buy.currency, buy.p2sh)
|
|
||||||
sell_p2sh_balance = check_p2sh(sell.currency, sell.p2sh)
|
|
||||||
|
|
||||||
if buy_p2sh_balance == 0:
|
|
||||||
print("Buy amt:", buy.amount)
|
|
||||||
txid = fund_buy_contract(trade)
|
|
||||||
print("Fund tx txid:", txid)
|
|
||||||
else:
|
|
||||||
raise ValueError("Sell p2sh not funded, buyer cannot redeem")
|
|
||||||
|
|
||||||
def redeem_one(trade):
|
|
||||||
buy = trade.buy
|
|
||||||
if trade.sell.get_status() == 'redeemed':
|
|
||||||
raise RuntimeError("Sell contract status was already redeemed before seller could redeem buyer's tx")
|
|
||||||
else:
|
|
||||||
secret = get_secret()
|
|
||||||
print("GETTING SECRET IN TEST:", secret)
|
|
||||||
tx_type, txid = redeem_p2sh(trade.buy, secret)
|
|
||||||
print("\nTX Type", tx_type)
|
|
||||||
setattr(trade.buy, tx_type, txid)
|
|
||||||
save(trade)
|
|
||||||
print("You have redeemed {0} {1}!".format(buy.amount, buy.currency))
|
|
||||||
|
|
||||||
def redeem_two(trade):
|
|
||||||
if trade.sell.get_status() == 'redeemed':
|
|
||||||
raise RuntimeError("Sell contract was redeemed before buyer could retrieve funds")
|
|
||||||
elif trade.buy.get_status() == 'refunded':
|
|
||||||
print("buy was refunded to buyer")
|
|
||||||
else:
|
|
||||||
# Buy contract is where seller disclosed secret in redeeming
|
|
||||||
if trade.buy.currency == 'bitcoin':
|
|
||||||
secret = bXcat.parse_secret(trade.buy.redeem_tx)
|
|
||||||
else:
|
|
||||||
secret = zXcat.parse_secret(trade.buy.redeem_tx)
|
|
||||||
print("Found secret in seller's redeem tx", secret)
|
|
||||||
redeem_tx = redeem_p2sh(trade.sell, secret)
|
|
||||||
setattr(trade.sell, 'redeem_tx', redeem_tx)
|
|
||||||
save(trade)
|
|
||||||
|
|
||||||
def generate_blocks(num):
|
|
||||||
bXcat.generate(num)
|
|
||||||
zXcat.generate(num)
|
|
||||||
|
|
||||||
initiate(htlcTrade)
|
|
||||||
fulfill(htlcTrade)
|
|
||||||
|
|
||||||
generate_blocks(6)
|
|
||||||
|
|
||||||
redeem_one(htlcTrade)
|
|
||||||
redeem_two(htlcTrade)
|
|
||||||
|
|
||||||
# addr = CBitcoinAddress('tmFRXyju7ANM7A9mg75ZjyhFW1UJEhUPwfQ')
|
|
||||||
# print(addr)
|
|
||||||
# # print(b2x('tmFRXyju7ANM7A9mg75ZjyhFW1UJEhUPwfQ'))
|
|
||||||
# print(b2x(addr))
|
|
|
@ -92,11 +92,6 @@ if not os.path.exists(tmp_dir):
|
||||||
xcatjson = os.path.join(tmp_dir, 'xcat.json')
|
xcatjson = os.path.join(tmp_dir, 'xcat.json')
|
||||||
|
|
||||||
|
|
||||||
def save_trade(trade):
|
|
||||||
with open(xcatjson, 'w+') as outfile:
|
|
||||||
json.dump(trade, outfile)
|
|
||||||
|
|
||||||
|
|
||||||
def get_trade():
|
def get_trade():
|
||||||
with open(xcatjson) as data_file:
|
with open(xcatjson) as data_file:
|
||||||
xcatdb = json.load(data_file)
|
xcatdb = json.load(data_file)
|
||||||
|
@ -113,7 +108,7 @@ def erase_trade():
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# Dumping trade to json file for development and debugging
|
||||||
def save(trade):
|
def save(trade):
|
||||||
# print("Saving trade")
|
# print("Saving trade")
|
||||||
trade = {
|
trade = {
|
||||||
|
@ -123,6 +118,9 @@ def save(trade):
|
||||||
}
|
}
|
||||||
save_trade(trade)
|
save_trade(trade)
|
||||||
|
|
||||||
|
def save_trade(trade):
|
||||||
|
with open(xcatjson, 'w+') as outfile:
|
||||||
|
json.dump(trade, outfile)
|
||||||
|
|
||||||
# Remove tmp files when trade is complete
|
# Remove tmp files when trade is complete
|
||||||
def cleanup(tradeid):
|
def cleanup(tradeid):
|
||||||
|
|
|
@ -23,3 +23,8 @@ ADDRS = {
|
||||||
"amounts": {'buy': {'currency': 'zcash', 'amount': 0.02}, 'sell': {'currency': 'bitcoin', 'amount': 0.01}}
|
"amounts": {'buy': {'currency': 'zcash', 'amount': 0.02}, 'sell': {'currency': 'bitcoin', 'amount': 0.01}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NETWORK = 'testnet'
|
||||||
|
|
||||||
|
# Pass regtest trade data in on command line
|
||||||
|
# '[{"initiator": {"bitcoin": "mvc56qCEVj6p57xZ5URNC3v7qbatudHQ9b", "zcash": "tmTF7LMLjvEsGdcepWPUsh4vgJNrKMWwEyc"}, "fulfiller": {"bitcoin": "moRt56gJQGDNK46Y6fYy2HbooKnQXrTGDN", "zcash": "tmK3rGzHDqa78MCwEicx9VcY9ZWX9gCF2nd"}, "amounts": {"buy": {"currency": "zcash", "amount": 0.02}, "sell": {"currency": "bitcoin", "amount": 0.01}}}]'
|
||||||
|
|
|
@ -51,7 +51,8 @@ class zcashProxy():
|
||||||
redeemerAddr = CBitcoinAddress(redeemer)
|
redeemerAddr = CBitcoinAddress(redeemer)
|
||||||
if type(commitment) == str:
|
if type(commitment) == str:
|
||||||
commitment = x(commitment)
|
commitment = x(commitment)
|
||||||
# h = sha256(secret)
|
else:
|
||||||
|
raise ValueError("Commitment was not a string: {0}".format(commitment))
|
||||||
blocknum = self.zcashd.getblockcount()
|
blocknum = self.zcashd.getblockcount()
|
||||||
print("Current blocknum on Zcash: ", blocknum)
|
print("Current blocknum on Zcash: ", blocknum)
|
||||||
redeemblocknum = blocknum + locktime
|
redeemblocknum = blocknum + locktime
|
||||||
|
|
Loading…
Reference in New Issue