Complete workflow
This commit is contained in:
parent
c832698870
commit
11101c98d0
14
bXcat.py
14
bXcat.py
|
@ -135,19 +135,19 @@ def redeem(p2sh, action):
|
|||
preimage = secret.encode('utf-8')
|
||||
print('preimage', preimage)
|
||||
|
||||
print('zec_redeemScript', zec_redeemScript)
|
||||
# print('zec_redeemScript', zec_redeemScript)
|
||||
txin.scriptSig = CScript([sig, privkey.pub, preimage, OP_TRUE, zec_redeemScript])
|
||||
print("Redeem tx hex:", b2x(tx.serialize()))
|
||||
# print("Redeem tx hex:", b2x(tx.serialize()))
|
||||
|
||||
# Can only call to_p2sh_scriptPubKey on CScript obj
|
||||
txin_scriptPubKey = zec_redeemScript.to_p2sh_scriptPubKey()
|
||||
|
||||
print("txin.scriptSig", b2x(txin.scriptSig))
|
||||
print("txin_scriptPubKey", b2x(txin_scriptPubKey))
|
||||
print('tx', tx)
|
||||
# print("txin.scriptSig", b2x(txin.scriptSig))
|
||||
# print("txin_scriptPubKey", b2x(txin_scriptPubKey))
|
||||
# print('tx', tx)
|
||||
VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,))
|
||||
print("script verified, sending raw tx")
|
||||
print("Raw tx", b2x(tx.serialize()))
|
||||
print("Script verified, sending raw tx...")
|
||||
print("Raw tx of prepared redeem tx: ", b2x(tx.serialize()))
|
||||
txid = bitcoind.sendrawtransaction(tx)
|
||||
txhex = b2x(lx(b2x(txid)))
|
||||
print("Txid of submitted redeem tx: ", txhex)
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"t27tZqKoQhdCcDeNL2cghne6RiCA5cR4vS9": {"p2sh": "t27tZqKoQhdCcDeNL2cghne6RiCA5cR4vS9", "redeemer": "tmFRXyju7ANM7A9mg75ZjyhFW1UJEhUPwfQ", "funder": "tmTjZSg4pX2Us6V5HttiwFZwj464fD2ZgpY", "redeemblocknum": 182, "zec_redeemScript": "63a8209f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a088876a9143ea29256c9d2888ca23de42a8b8e69ca2ec235b16702b600b17576a914c5acca6ef39c843c7a9c3ad01b2da95fe2edf5ba6888ac"}, "2MwNfS9dETRaJRNM9jU14NXvSg8L2Suqygx": {"p2sh": "2MwNfS9dETRaJRNM9jU14NXvSg8L2Suqygx", "redeemer": "mrQzUGU1dwsWRx5gsKKSDPNtrsP65vCA3Z", "funder": "myfFr5twPYNwgeXyjCmGcrzXtCmfmWXKYp", "redeemblocknum": 146, "zec_redeemScript": "63a8209f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a088876a9147788b4511a25fba1092e67b307a6dcdb6da125d967029200b17576a914c7043e62a7391596116f54f6a64c8548e97d3fd96888ac"}}
|
||||
{"t2QVxM3CdtjTtXC7P9eNvUoL22DWp7CzxFq": {"funder": "tmTjZSg4pX2Us6V5HttiwFZwj464fD2ZgpY", "zec_redeemScript": "63a820936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af8876a9143ea29256c9d2888ca23de42a8b8e69ca2ec235b16702b600b17576a914c5acca6ef39c843c7a9c3ad01b2da95fe2edf5ba6888ac", "redeemblocknum": 182, "p2sh": "t2QVxM3CdtjTtXC7P9eNvUoL22DWp7CzxFq", "redeemer": "tmFRXyju7ANM7A9mg75ZjyhFW1UJEhUPwfQ"}, "2N8TRB2xd9Xfsk7LuMif4CuPf8tQf5dSrdU": {"funder": "myfFr5twPYNwgeXyjCmGcrzXtCmfmWXKYp", "zec_redeemScript": "63a820936a185caaa266bb9cbe981e9e05cb78cd732b0b3280eb944412bb6f8f8f07af8876a9147788b4511a25fba1092e67b307a6dcdb6da125d967029200b17576a914c7043e62a7391596116f54f6a64c8548e97d3fd96888ac", "redeemblocknum": 146, "p2sh": "2N8TRB2xd9Xfsk7LuMif4CuPf8tQf5dSrdU", "redeemer": "mrQzUGU1dwsWRx5gsKKSDPNtrsP65vCA3Z"}}
|
7
utils.py
7
utils.py
|
@ -13,8 +13,11 @@ def save_trade(trade):
|
|||
|
||||
def get_trade():
|
||||
with open('xcat.json') as data_file:
|
||||
xcatdb = json.load(data_file)
|
||||
return xcatdb
|
||||
try:
|
||||
xcatdb = json.load(data_file)
|
||||
return xcatdb
|
||||
except:
|
||||
return None
|
||||
|
||||
def get_contract():
|
||||
with open('contract.json') as data_file:
|
||||
|
|
|
@ -1 +1 @@
|
|||
{"id": 1, "sell": {"initiator": "myfFr5twPYNwgeXyjCmGcrzXtCmfmWXKYp", "currency": "bitcoin", "fund_tx": "3796f3ccd8ecc2b11603862648e09e7d95d3cbbe869c25f59484abcecd85f2db", "p2sh": "2MwNfS9dETRaJRNM9jU14NXvSg8L2Suqygx", "status": "redeemed", "fulfiller": "mrQzUGU1dwsWRx5gsKKSDPNtrsP65vCA3Z", "redeem_tx": "e814851af2676e4e981e6acae567071cc3531b5102239de211d4ab926e5d92ad", "amount": 1.2, "secret": "test"}, "buy": {"status": "redeemed", "redeem_tx": "d95a802145b7810c9cf1df925ab1f498d14a81c6b09b4d2e00c77e19ec6ad481", "fund_tx": "b96ab6c8112af25c2c288d983bcdb094c644f097c526d20f8493f1af39ce7d72", "amount": 2.45, "initiator": "tmFRXyju7ANM7A9mg75ZjyhFW1UJEhUPwfQ", "fulfiller": "tmTjZSg4pX2Us6V5HttiwFZwj464fD2ZgpY", "currency": "zcash", "p2sh": "t27tZqKoQhdCcDeNL2cghne6RiCA5cR4vS9"}}
|
||||
{"sell": {"secret": "helloworld", "fulfiller": "mrQzUGU1dwsWRx5gsKKSDPNtrsP65vCA3Z", "status": "redeemed", "currency": "bitcoin", "amount": 3.5, "initiator": "myfFr5twPYNwgeXyjCmGcrzXtCmfmWXKYp", "p2sh": "2N8TRB2xd9Xfsk7LuMif4CuPf8tQf5dSrdU", "redeem_tx": "e0947a300016faa5b4f2ff64e5e5c98cb09a1f14f4de68098b3e2679514c8432", "fund_tx": "a943ef89fafe60d82e00129bb5bf51f3c597b7f65bf464df41da7685b88270d7"}, "id": 1, "buy": {"currency": "zcash", "fulfiller": "tmTjZSg4pX2Us6V5HttiwFZwj464fD2ZgpY", "status": "redeemed", "amount": 1.2, "p2sh": "t2QVxM3CdtjTtXC7P9eNvUoL22DWp7CzxFq", "initiator": "tmFRXyju7ANM7A9mg75ZjyhFW1UJEhUPwfQ", "redeem_tx": "de46faa86b51fcb41694a8b9937ac7ef095801025478544bdb32fa18ef92ffc9", "fund_tx": "5ab08aee8412b5e660a72d5871d2c1435ae21a244476c785d2941e1652c06403"}}
|
86
xcat.py
86
xcat.py
|
@ -4,7 +4,7 @@ from utils import *
|
|||
from waiting import *
|
||||
from time import sleep
|
||||
import json
|
||||
import os
|
||||
import os, sys
|
||||
from pprint import pprint
|
||||
|
||||
def check_p2sh(currency, address):
|
||||
|
@ -22,9 +22,13 @@ def set_price():
|
|||
sell = 'bitcoin'
|
||||
buy = 'zcash'
|
||||
sell_amt = input("How much {0} do you want to sell?".format(sell))
|
||||
sell_amt = 3.5
|
||||
print(sell_amt)
|
||||
buy_amt = input("How much {0} do you want to receive in exchange?".format(buy))
|
||||
sell = {'currency': sell, 'amount': 1.2}
|
||||
buy = {'currency': buy, 'amount': 2.45}
|
||||
buy_amt = 1.2
|
||||
print(buy_amt)
|
||||
sell = {'currency': sell, 'amount': sell_amt}
|
||||
buy = {'currency': buy, 'amount': buy_amt}
|
||||
trade['sell'] = sell
|
||||
trade['buy'] = buy
|
||||
save_trade(trade)
|
||||
|
@ -48,7 +52,8 @@ def initiate_trade():
|
|||
currency = trade['sell']['currency']
|
||||
secret = input("Initiating trade: Enter a password to place the {0} you want to sell in escrow: ".format(currency))
|
||||
# TODO: hash and store secret only locally.
|
||||
secret = 'test'
|
||||
# secret = 'test'
|
||||
print('Remember your password:', secret)
|
||||
locktime = 20 # Must be more than first tx
|
||||
|
||||
# Returns contract obj
|
||||
|
@ -76,12 +81,12 @@ def initiate_trade():
|
|||
buy_currency = trade['buy']['currency']
|
||||
buy_initiator = trade['buy']['initiator']
|
||||
buy_fulfiller = trade['buy']['fulfiller']
|
||||
print("Now creating buy contract on the {0} blockchain where you will wait for fulfiller to send funds...".format(buy_currency))
|
||||
print("Now creating buy contract on the {0} blockchain where you will wait for the buyer to send funds...".format(buy_currency))
|
||||
buy_contract = create_htlc(buy_currency, buy_fulfiller, buy_initiator, secret, locktime)
|
||||
buy_p2sh = buy_contract['p2sh']
|
||||
contracts[buy_contract['p2sh']] = buy_contract
|
||||
save_contract(contracts)
|
||||
print("Waiting for buyer to send funds to this p2sh", buy_p2sh)
|
||||
print("Now contact the buyer and tell them to send funds to this p2sh: ", buy_p2sh)
|
||||
|
||||
trade['buy']['p2sh'] = buy_p2sh
|
||||
|
||||
|
@ -109,8 +114,8 @@ def get_addresses():
|
|||
print(fulfill_offer_addr)
|
||||
fulfill_bid_addr = input("Enter the {0} address of the party you want to trade with: ".format(buy))
|
||||
# fulfill_bid_addr = zXcat.new_zcash_addr()
|
||||
print(fulfill_bid_addr)
|
||||
fulfill_bid_addr = 'tmTjZSg4pX2Us6V5HttiwFZwj464fD2ZgpY'
|
||||
print(fulfill_bid_addr)
|
||||
trade['sell']['fulfiller'] = fulfill_offer_addr
|
||||
trade['buy']['fulfiller'] = fulfill_bid_addr
|
||||
|
||||
|
@ -167,13 +172,17 @@ def redeem_p2sh(currency, p2sh, action):
|
|||
def seller_redeem():
|
||||
# add locktime as variable?
|
||||
trade = get_trade()
|
||||
# Seller redeems buyer's funded tx (contract in p2sh)
|
||||
p2sh = trade['buy']['p2sh']
|
||||
currency = trade['buy']['currency']
|
||||
redeem_tx = redeem_p2sh(currency, p2sh, 'buy')
|
||||
trade['buy']['redeem_tx'] = redeem_tx
|
||||
trade['buy']['status'] = 'redeemed'
|
||||
save_trade(trade)
|
||||
if trade['buy']['status'] == 'redeemed':
|
||||
print("You already redeemed the funds and acquired {0} {1}".format(trade['buy']['amount'], trade['buy']['currency']))
|
||||
exit()
|
||||
else:
|
||||
# Seller redeems buyer's funded tx (contract in p2sh)
|
||||
p2sh = trade['buy']['p2sh']
|
||||
currency = trade['buy']['currency']
|
||||
redeem_tx = redeem_p2sh(currency, p2sh, 'buy')
|
||||
trade['buy']['redeem_tx'] = redeem_tx
|
||||
trade['buy']['status'] = 'redeemed'
|
||||
save_trade(trade)
|
||||
|
||||
def buyer_redeem():
|
||||
trade = get_trade()
|
||||
|
@ -187,45 +196,58 @@ def buyer_redeem():
|
|||
|
||||
if __name__ == '__main__':
|
||||
print("ZEC <-> BTC XCAT (Cross-Chain Atomic Transactions)")
|
||||
role = input("Would you like to initiate or accept a trade?")
|
||||
# Have initiator propose amounts to trade
|
||||
|
||||
# TODO: Get trade indicated by id number
|
||||
# TODO: pass trade into functions?
|
||||
# TODO: workflow framed as currency you're trading out of being sell. appropriate?
|
||||
# Have initiator propose amounts to trade
|
||||
trade = get_trade()
|
||||
|
||||
# If there is no status on a sell order (for this json file db...) we assume you must initiate_trade
|
||||
if 'status' not in trade['sell']:
|
||||
role = 'i'
|
||||
elif trade['sell']['status'] == 'redeemed' and trade['buy']['status'] == 'redeemed':
|
||||
print("This trade is already complete! Trade details:")
|
||||
pprint(trade)
|
||||
exit()
|
||||
try:
|
||||
role = sys.argv[1]
|
||||
print("Your role in demo:", role)
|
||||
except:
|
||||
if trade == None:
|
||||
print("No active trades available.")
|
||||
res = input("Would you like to initiate a trade? (y/n) ")
|
||||
if res == 'y':
|
||||
role = 'seller'
|
||||
else:
|
||||
exit()
|
||||
else:
|
||||
print("Trade exists, run script as buyer or seller to complete trade.")
|
||||
exit()
|
||||
|
||||
if role == "i":
|
||||
if 'status' not in trade['sell']:
|
||||
if trade is not None:
|
||||
if trade['sell']['status'] == 'redeemed' and trade['buy']['status'] == 'redeemed':
|
||||
print("This trade is already complete! Trade details:")
|
||||
pprint(trade)
|
||||
exit()
|
||||
|
||||
if role == "seller":
|
||||
if trade == None or 'status' not in trade['sell']:
|
||||
set_price()
|
||||
get_addresses()
|
||||
initiate_trade()
|
||||
print("XCATDB Trade", trade)
|
||||
print("Status of XCAT trade:")
|
||||
pprint(get_trade())
|
||||
elif 'status' in trade['sell']:
|
||||
if trade['sell']['status'] == 'funded':
|
||||
# Means buyer has already funded the currency the transaction initiator wants to exchange into
|
||||
print("Buyer funded the contract where you offered to buy {0}, redeeming funds from {1}...".format(trade['buy']['currency'], trade['buy']['p2sh']))
|
||||
seller_redeem()
|
||||
else:
|
||||
if trade['buy']['status'] == 'redeemed':
|
||||
# Seller has redeemed buyer's tx, buyer can now redeem.
|
||||
print("The seller has redeemed the contract where you paid them in {0}, now redeeming your funds from {1}".format(trade['buy']['currency'], trade['sell']['p2sh']))
|
||||
buyer_redeem()
|
||||
elif trade['sell']['status'] == 'funded':
|
||||
if 'status' not in trade['buy'] and trade['sell']['status'] == 'funded':
|
||||
print("One active trade available, fulfilling buyer contract...")
|
||||
trade = get_trade()
|
||||
buyer_fulfill()
|
||||
# How to monitor if txs are included in blocks -- should use blocknotify and a monitor daemon?
|
||||
# For regtest, can mock in a function
|
||||
# p2sh = trade['buy']['p2sh']
|
||||
# check_blocks(p2sh)
|
||||
elif trade['buy']['status'] == 'redeemed':
|
||||
# Seller has redeemed buyer's tx, buyer can now redeem.
|
||||
print("The seller has redeemed the contract where you paid them in {0}, now redeeming your funds from {1}".format(trade['buy']['currency'], trade['sell']['p2sh']))
|
||||
buyer_redeem()
|
||||
|
||||
pprint(get_trade())
|
||||
|
||||
|
|
16
zXcat.py
16
zXcat.py
|
@ -43,7 +43,7 @@ def hashtimelockcontract(funder, redeemer, secret, locktime):
|
|||
zec_redeemScript = CScript([OP_IF, OP_SHA256, h, OP_EQUALVERIFY,OP_DUP, OP_HASH160,
|
||||
redeemerAddr, OP_ELSE, redeemblocknum, OP_CHECKLOCKTIMEVERIFY, OP_DROP, OP_DUP, OP_HASH160,
|
||||
funderAddr, OP_ENDIF,OP_EQUALVERIFY, OP_CHECKSIG])
|
||||
print("TX2 Redeem script on Zcash blockchain:", b2x(zec_redeemScript))
|
||||
print("Redeem script for p2sh contract on Zcash blockchain:", b2x(zec_redeemScript))
|
||||
txin_scriptPubKey = zec_redeemScript.to_p2sh_scriptPubKey()
|
||||
# Convert the P2SH scriptPubKey to a base58 Bitcoin address
|
||||
txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey)
|
||||
|
@ -110,19 +110,19 @@ def redeem(p2sh, action):
|
|||
preimage = secret.encode('utf-8')
|
||||
print('preimage', preimage)
|
||||
|
||||
print('zec_redeemScript', zec_redeemScript)
|
||||
# print('zec_redeemScript', zec_redeemScript)
|
||||
txin.scriptSig = CScript([sig, privkey.pub, preimage, OP_TRUE, zec_redeemScript])
|
||||
print("Redeem tx hex:", b2x(tx.serialize()))
|
||||
# print("Redeem tx hex:", b2x(tx.serialize()))
|
||||
|
||||
# Can only call to_p2sh_scriptPubKey on CScript obj
|
||||
txin_scriptPubKey = zec_redeemScript.to_p2sh_scriptPubKey()
|
||||
|
||||
print("txin.scriptSig", b2x(txin.scriptSig))
|
||||
print("txin_scriptPubKey", b2x(txin_scriptPubKey))
|
||||
print('tx', tx)
|
||||
# print("txin.scriptSig", b2x(txin.scriptSig))
|
||||
# print("txin_scriptPubKey", b2x(txin_scriptPubKey))
|
||||
# print('tx', tx)
|
||||
VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,))
|
||||
print("script verified, sending raw tx")
|
||||
print("Raw tx", b2x(tx.serialize()))
|
||||
print("Script verified, sending raw tx...")
|
||||
print("Raw tx of prepared redeem tx: ", b2x(tx.serialize()))
|
||||
txid = zcashd.sendrawtransaction(tx)
|
||||
txhex = b2x(lx(b2x(txid)))
|
||||
print("Txid of submitted redeem tx: ", txhex)
|
||||
|
|
Loading…
Reference in New Issue