Repackage as python module

This commit is contained in:
Jay Graber 2017-07-28 17:23:32 -07:00
parent 043958b840
commit 94abea7bc2
21 changed files with 147 additions and 61 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
*.pyc
xcatdb/
xcat.egg-info/

View File

@ -1,2 +0,0 @@
python-bitcoinlib
plyvel

View File

@ -1 +0,0 @@
2E8ASX0w

17
setup.py Normal file
View File

@ -0,0 +1,17 @@
#!/usr/bin/env python
from setuptools import setup, find_packages
from xcat import version
setup(
name="xcat",
version=version,
entry_points = {
"console_scripts": ['xcat = xcat.cli:main']
},
description="Xcat is a package to facilitate cross-chain atomic transactions.",
author="arcalinea and arielgabizon",
author_email="xcat@z.cash",
license="MIT",
url="http://github.com/zcash/xcat",
packages=find_packages()
)

7
xcat-runner.py Normal file
View File

@ -0,0 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from xcat.xcat import main
if __name__ == '__main__':
main()

5
xcat/__init__.py Normal file
View File

@ -0,0 +1,5 @@
"""
Xcat is an implementation of a cross-chain atomic transaction. The protocol currently support trades between Zcash and Bitcoin.
"""
version_info = (0, 1)
version = '.'.join(map(str, version_info))

2
xcat/__main__.py Normal file
View File

@ -0,0 +1,2 @@
from .cli import main
main()

View File

@ -14,13 +14,13 @@ from bitcoin.core.script import CScript, OP_DUP, OP_IF, OP_ELSE, OP_ENDIF, OP_HA
from bitcoin.core.scripteval import VerifyScript, SCRIPT_VERIFY_P2SH
from bitcoin.wallet import CBitcoinAddress, CBitcoinSecret, P2SHBitcoinAddress, P2PKHBitcoinAddress
from utils import *
from xcat.utils import *
import zcash
import zcash.rpc
import pprint, json
from zXcat import parse_script
from xcat.zcashRPC import parse_script
# SelectParams('testnet')
SelectParams('regtest')

View File

@ -1,14 +1,16 @@
import argparse, textwrap
from utils import *
import database as db
import bXcat, zXcat
from trades import *
from xcat import *
from xcat.utils import *
import xcat.database as db
import xcat.bitcoinRPC
import xcat.zcashRPC
import xcat.userInput
from xcat.trades import *
from xcat.protocol import *
import ast
def save_state(trade):
def save_state(trade, tradeid):
save(trade)
db.create
db.create(trade, tradeid)
def checkSellStatus(trade):
if trade.buy.get_status() == 'funded':
@ -49,38 +51,58 @@ def checkBuyStatus(trade):
print("TXID after buyer redeem", txid)
print("XCAT trade complete!")
# Import a trade in hex, and save to db
def importtrade(hexstr):
trade = x2s(hexstr)
trade = instantiateTrade(ast.literal_eval(trade))
save_state(trade)
# Export a trade by its tradeid
def exporttrade(tradeid):
# trade = get_trade()
trade = db.get(tradeid)
hexstr = s2x(str(trade))
print(trade)
print(hexstr)
def newtrade(tradeid):
erase_trade()
role = 'seller'
print("Creating new XCAT trade...")
trade = seller_init(Trade())
# Save it to leveldb
# db.create(trade)
save_state(trade, tradeid)
def instantiateTrade(trade):
return Trade(buy=Contract(trade['buy']), sell=Contract(trade['sell']))
if __name__ == '__main__':
def main():
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter,
description=textwrap.dedent('''\
== Trades ==
newtrade - create a new trade
checktrades - check for actions to be taken on existing trades
importtrade "hexstr" - import an existing trade from a hex string
exporttrade - export the data of an existing xcat trade as a hex string
exporttrade - export the data of an existing trade as a hex string. Takes the tradeid as an argument
findtrade - find a trade by the txid of the currency being traded out of
'''))
parser.add_argument("command", action="store", help="list commands")
parser.add_argument("argument", action="store", nargs="*", help="add an argument")
# parser.add_argument("--daemon", "-d", action="store_true", help="Run as daemon process")
# TODO: function to view available trades
# TODO: function to tell if tradeid already exists for newtrade
args = parser.parse_args()
# how to hold state of role
command = args.command
if command == 'importtrade':
hexstr = args.argument[0]
trade = x2s(hexstr)
trade = instantiateTrade(ast.literal_eval(trade))
save_state(trade)
# print(trade.toJ)
importtrade(hexstr)
elif command == 'exporttrade':
trade = get_trade()
hexstr = s2x(str(trade))
print(trade)
print(hexstr)
tradeid = args.argument[0]
exporttrade(tradeid)
elif command == 'checktrades':
trade = get_trade()
trade = instantiateTrade(trade)
@ -91,12 +113,12 @@ if __name__ == '__main__':
role = 'buyer'
checkBuyStatus(trade)
elif command == 'newtrade':
erase_trade()
role = 'seller'
print("Creating new XCAT trade...")
trade = seller_init(Trade())
# Save it to leveldb
db.create(trade)
try:
tradeid = args.argument[0]
newtrade(tradeid)
except:
tradeid = userInput.enter_trade_id()
newtrade(tradeid)
elif command == "daemon":
#TODO: implement
print("Run as daemon process")

View File

@ -1,29 +1,35 @@
import plyvel
from utils import *
from .utils import *
import binascii
import sys
import json
db = plyvel.DB('/tmp/testdb', create_if_missing=True)
trade = get_trade()
## txid we retrieve by
if trade and trade.sell:
if hasattr(trade.sell, 'fund_tx'):
txid = trade.sell.fund_tx
# trade = get_trade()
# ## txid we retrieve by
# if trade and trade.sell:
# if hasattr(trade.sell, 'fund_tx'):
# txid = trade.sell.fund_tx
# Takes object, saves json as bytes
def create(trade):
def create(trade, tradeid):
trade = trade.toJSON()
db.put(b(tradeid), b(trade))
# Uses the funding txid as the key to save trade
def createByFundtx(trade):
trade = trade.toJSON()
# # Save trade by initiating txid
jt = json.loads(trade)
txid = jt['sell']['fund_tx']
# Save trade by initiating txid
db.put(b(txid), b(trade))
def get(txid):
return db.get(b(txid))
# db.delete(b'hello')
db.get(b'test')
# hexstr = get(txid)
# print(x2s(hexstr))
@ -33,8 +39,9 @@ def print_entries():
with db.iterator() as it:
for k, v in it:
j = json.loads(x2s(b2x(v)))
print("Key:", k)
print('val: ', j)
print('sell: ', j['sell'])
# print('sell: ', j['sell'])
# print_entries()
# txid = '1171aeda64eff388b3568fa4675d0ca78852911109bbe42e0ef11ad6bf1b159e'

View File

@ -1,35 +1,35 @@
import zXcat
import bXcat
from utils import *
from waiting import *
from time import sleep
import json
import os, sys
from pprint import pprint
from trades import Contract, Trade
import userInput
import xcat.zcashRPC
import xcat.bitcoinRPC
from xcat.utils import *
from xcat.trades import Contract, Trade
import xcat.userInput
def check_p2sh(currency, address):
if currency == 'bitcoin':
print("Checking funds in Bitcoin p2sh")
return bXcat.check_funds(address)
return bitcoinRPC.check_funds(address)
else:
print("Checking funds in Zcash p2sh")
return zXcat.check_funds(address)
return zcashRPC.check_funds(address)
def create_htlc(currency, funder, redeemer, commitment, locktime):
print("Commitment in create_htlc", commitment)
if currency == 'bitcoin':
sell_p2sh = bXcat.hashtimelockcontract(funder, redeemer, commitment, locktime)
sell_p2sh = bitcoinRPC.hashtimelockcontract(funder, redeemer, commitment, locktime)
else:
sell_p2sh = zXcat.hashtimelockcontract(funder, redeemer, commitment, locktime)
sell_p2sh = zcashRPC.hashtimelockcontract(funder, redeemer, commitment, locktime)
return sell_p2sh
def fund_htlc(currency, p2sh, amount):
if currency == 'bitcoin':
txid = bXcat.fund_htlc(p2sh, amount)
txid = bitcoinRPC.fund_htlc(p2sh, amount)
else:
txid = zXcat.fund_htlc(p2sh, amount)
txid = zcashRPC.fund_htlc(p2sh, amount)
return txid
#
# def fund_buy_contract(trade):
@ -80,25 +80,25 @@ def create_buy_p2sh(trade, commitment, locktime):
def auto_redeem_p2sh(contract, secret):
currency = contract.currency
if currency == 'bitcoin':
res = bXcat.auto_redeem(contract, secret)
res = bitcoinRPC.auto_redeem(contract, secret)
else:
res = zXcat.auto_redeem(contract, secret)
res = zcashRPC.auto_redeem(contract, secret)
return res
def redeem_p2sh(contract, secret):
currency = contract.currency
if currency == 'bitcoin':
res = bXcat.redeem_contract(contract, secret)
res = bitcoinRPC.redeem_contract(contract, secret)
else:
res = zXcat.redeem_contract(contract, secret)
res = zcashRPC.redeem_contract(contract, secret)
return res
def parse_secret(chain, txid):
if chain == 'bitcoin':
secret = bXcat.parse_secret(txid)
secret = bitcoinRPC.parse_secret(txid)
else:
secret = zXcat.parse_secret(txid)
secret = zcashRPC.parse_secret(txid)
#### Main functions determining user flow from command line
def buyer_redeem(trade):
@ -112,9 +112,9 @@ def buyer_redeem(trade):
currency = trade.sell.currency
# Buy contract is where seller disclosed secret in redeeming
if trade.buy.currency == 'bitcoin':
secret = bXcat.parse_secret(trade.buy.redeem_tx)
secret = bitcoinRPC.parse_secret(trade.buy.redeem_tx)
else:
secret = zXcat.parse_secret(trade.buy.redeem_tx)
secret = zcashRPC.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)

1
xcat/secret.json Normal file
View File

@ -0,0 +1 @@
OBbU9kny

View File

@ -1,5 +1,5 @@
import zXcat
import bXcat
import xcat.zcash
import xcat.bitcoin
from xcat import *
htlcTrade = Trade()

21
xcat/tests/test_db.py Normal file
View File

@ -0,0 +1,21 @@
import xcat.database as db
import unittest, json
import xcat.trades as trades
class DatabaseTest(unittest.TestCase):
def setUp(self):
self.data = {"sell": {"amount": 3.5, "redeemScript": "63a82003d58daab37238604b3e57d4a8bdcffa401dc497a9c1aa4f08ffac81616c22b68876a9147788b4511a25fba1092e67b307a6dcdb6da125d967022a04b17576a914c7043e62a7391596116f54f6a64c8548e97d3fd96888ac", "redeemblocknum": 1066, "currency": "bitcoin", "initiator": "myfFr5twPYNwgeXyjCmGcrzXtCmfmWXKYp", "p2sh": "2MuYSQ1uQ4CJg5Y5QL2vMmVPHNJ2KT5aJ6f", "fulfiller": "mrQzUGU1dwsWRx5gsKKSDPNtrsP65vCA3Z", "fund_tx": "5c5e91a89a08b2d6698f50c9fd9bb2fa22da6c74e226c3dd63d59511566a2fdb"}, "buy": {"amount": 1.2, "redeemScript": "63a82003d58daab37238604b3e57d4a8bdcffa401dc497a9c1aa4f08ffac81616c22b68876a9143ea29256c9d2888ca23de42a8b8e69ca2ec235b167023f0db17576a914c5acca6ef39c843c7a9c3ad01b2da95fe2edf5ba6888ac", "redeemblocknum": 3391, "currency": "zcash", "locktime": 10, "initiator": "tmFRXyju7ANM7A9mg75ZjyhFW1UJEhUPwfQ", "p2sh": "t2HP59RpfR34nBCWH4VVD497tkc2ikzgniP", "fulfiller": "tmTjZSg4pX2Us6V5HttiwFZwj464fD2ZgpY"}, "commitment": "03d58daab37238604b3e57d4a8bdcffa401dc497a9c1aa4f08ffac81616c22b6"}
self.sell = trades.Contract(self.data['sell'])
def test_create(self):
sell = trades.Contract(self.data['sell'])
buy = trades.Contract(self.data['buy'])
trade = trades.Trade(sell, buy, commitment=self.data['commitment'])
db.create(trade, 'test')
def test_get(self):
trade = db.get('test')
print("Trade")
if __name__ == '__main__':
unittest.main()

View File

@ -0,0 +1 @@
{"sell": {"amount": 3.5, "redeemScript": "63a82003d58daab37238604b3e57d4a8bdcffa401dc497a9c1aa4f08ffac81616c22b68876a9147788b4511a25fba1092e67b307a6dcdb6da125d967022a04b17576a914c7043e62a7391596116f54f6a64c8548e97d3fd96888ac", "redeemblocknum": 1066, "currency": "bitcoin", "initiator": "myfFr5twPYNwgeXyjCmGcrzXtCmfmWXKYp", "p2sh": "2MuYSQ1uQ4CJg5Y5QL2vMmVPHNJ2KT5aJ6f", "fulfiller": "mrQzUGU1dwsWRx5gsKKSDPNtrsP65vCA3Z", "fund_tx": "5c5e91a89a08b2d6698f50c9fd9bb2fa22da6c74e226c3dd63d59511566a2fdb"}, "buy": {"amount": 1.2, "redeemScript": "63a82003d58daab37238604b3e57d4a8bdcffa401dc497a9c1aa4f08ffac81616c22b68876a9143ea29256c9d2888ca23de42a8b8e69ca2ec235b167023f0db17576a914c5acca6ef39c843c7a9c3ad01b2da95fe2edf5ba6888ac", "redeemblocknum": 3391, "currency": "zcash", "locktime": 10, "initiator": "tmFRXyju7ANM7A9mg75ZjyhFW1UJEhUPwfQ", "p2sh": "t2HP59RpfR34nBCWH4VVD497tkc2ikzgniP", "fulfiller": "tmTjZSg4pX2Us6V5HttiwFZwj464fD2ZgpY"}, "commitment": "03d58daab37238604b3e57d4a8bdcffa401dc497a9c1aa4f08ffac81616c22b6"}

View File

@ -1,4 +1,8 @@
from utils import *
from xcat.utils import *
def enter_trade_id():
tradeid = input("Enter a unique identifier for this trade: ")
return tradeid
def get_trade_amounts():
amounts = {}

View File

@ -1,5 +1,5 @@
import hashlib, json, random, binascii
import trades
import xcat.trades
############################################
########### Data conversion utils ##########

1
xcat/xcat.json Normal file
View File

@ -0,0 +1 @@
{"sell": {"amount": 3.5, "redeemScript": "63a82003d58daab37238604b3e57d4a8bdcffa401dc497a9c1aa4f08ffac81616c22b68876a9147788b4511a25fba1092e67b307a6dcdb6da125d967022a04b17576a914c7043e62a7391596116f54f6a64c8548e97d3fd96888ac", "redeemblocknum": 1066, "currency": "bitcoin", "initiator": "myfFr5twPYNwgeXyjCmGcrzXtCmfmWXKYp", "p2sh": "2MuYSQ1uQ4CJg5Y5QL2vMmVPHNJ2KT5aJ6f", "fulfiller": "mrQzUGU1dwsWRx5gsKKSDPNtrsP65vCA3Z", "fund_tx": "5c5e91a89a08b2d6698f50c9fd9bb2fa22da6c74e226c3dd63d59511566a2fdb"}, "buy": {"amount": 1.2, "redeemScript": "63a82003d58daab37238604b3e57d4a8bdcffa401dc497a9c1aa4f08ffac81616c22b68876a9143ea29256c9d2888ca23de42a8b8e69ca2ec235b167023f0db17576a914c5acca6ef39c843c7a9c3ad01b2da95fe2edf5ba6888ac", "redeemblocknum": 3391, "currency": "zcash", "locktime": 10, "initiator": "tmFRXyju7ANM7A9mg75ZjyhFW1UJEhUPwfQ", "p2sh": "t2HP59RpfR34nBCWH4VVD497tkc2ikzgniP", "fulfiller": "tmTjZSg4pX2Us6V5HttiwFZwj464fD2ZgpY"}, "commitment": "03d58daab37238604b3e57d4a8bdcffa401dc497a9c1aa4f08ffac81616c22b6"}

View File

@ -16,7 +16,7 @@ from zcash.core.script import CScript, OP_DUP, OP_IF, OP_ELSE, OP_ENDIF, OP_HASH
from zcash.core.scripteval import VerifyScript, SCRIPT_VERIFY_P2SH
from zcash.wallet import CBitcoinAddress, CBitcoinSecret, P2SHBitcoinAddress, P2PKHBitcoinAddress
from utils import *
from xcat.utils import *
# SelectParams('testnet')
SelectParams('regtest')