Complete workflow

This commit is contained in:
Jay Graber 2017-05-23 13:34:48 -07:00
parent c832698870
commit 11101c98d0
6 changed files with 76 additions and 51 deletions

View File

@ -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)

View File

@ -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"}}

View File

@ -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:

View 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
View File

@ -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())

View File

@ -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)