diff --git a/bXcat.py b/bXcat.py index 533f78f..379eeb0 100644 --- a/bXcat.py +++ b/bXcat.py @@ -47,15 +47,15 @@ def get_keys(funder_address, redeemer_address): def privkey(address): bitcoind.dumpprivkey(address) -def hashtimelockcontract(funder, redeemer, secret, locktime): +def hashtimelockcontract(funder, redeemer, commitment, locktime): funderAddr = CBitcoinAddress(funder) redeemerAddr = CBitcoinAddress(redeemer) - h = sha256(secret) + # h = sha256(secret) blocknum = bitcoind.getblockcount() print("Current blocknum", blocknum) redeemblocknum = blocknum + locktime print("REDEEMBLOCKNUM BITCOIN", redeemblocknum) - redeemScript = CScript([OP_IF, OP_SHA256, h, OP_EQUALVERIFY,OP_DUP, OP_HASH160, + redeemScript = CScript([OP_IF, OP_SHA256, x(commitment), 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("Redeem script for p2sh contract on Bitcoin blockchain:", b2x(redeemScript)) @@ -108,6 +108,11 @@ def get_tx_details(txid): # redeems automatically after buyer has funded tx, by scanning for transaction to the p2sh # i.e., doesn't require buyer telling us fund txid def auto_redeem(contract, secret): + print("Parsing script for auto_redeem...") + scriptarray = parse_script(contract.redeemScript) + redeemblocknum = scriptarray[8] + redeemPubkey = scriptarray[6] + refundPubkey = scriptarray[13] # How to find redeemScript and redeemblocknum from blockchain? print("Contract in auto redeem", contract.__dict__) p2sh = contract.p2sh @@ -124,11 +129,11 @@ def auto_redeem(contract, secret): print("Found {0} in p2sh {1}, redeeming...".format(amount, p2sh)) # Parsing redeemblocknum from the redeemscript of the p2sh - redeemblocknum = find_redeemblocknum(contract) + # redeemblocknum = find_redeemblocknum(contract) blockcount = bitcoind.getblockcount() print("\nCurrent blocknum at time of redeem on Bitcoin:", blockcount) if blockcount < redeemblocknum: - redeemPubKey = find_redeemAddr(contract) + # redeemPubKey = find_redeemAddr(contract) print('redeemPubKey', redeemPubKey) else: print("nLocktime exceeded, refunding") @@ -169,7 +174,68 @@ def auto_redeem(contract, secret): else: print("No contract for this p2sh found in database", p2sh) +def redeem_contract(contract, secret): + # How to find redeemScript and redeemblocknum from blockchain? + print("Contract in redeem_contract", contract.__dict__) + p2sh = contract.p2sh + #checking there are funds in the address + amount = check_funds(p2sh) + if(amount == 0): + print("address ", p2sh, " not funded") + quit() + fundtx = find_transaction_to_address(p2sh) + amount = fundtx['amount'] / COIN + print("Found fundtx:", fundtx) + p2sh = P2SHBitcoinAddress(p2sh) + if fundtx['address'] == p2sh: + print("Found {0} in p2sh {1}, redeeming...".format(amount, p2sh)) + + # TODO: Decodescript is not working, add back in. + # redeemblocknum = find_redeemblocknum(contract) + + blockcount = bitcoind.getblockcount() + print("\nCurrent blocknum at time of redeem on Zcash:", blockcount) + if blockcount < contract.redeemblocknum: + + # redeemPubKey = find_redeemAddr(contract) + redeemPubKey = P2PKHBitcoinAddress.from_bytes(x('7788b4511a25fba1092e67b307a6dcdb6da125d9')) + + print('redeemPubKey', redeemPubKey) + zec_redeemScript = CScript(x(contract.redeemScript)) + txin = CMutableTxIn(fundtx['outpoint']) + txout = CMutableTxOut(fundtx['amount'] - FEE, redeemPubKey.to_scriptPubKey()) + # Create the unsigned raw transaction. + tx = CMutableTransaction([txin], [txout]) + sighash = SignatureHash(zec_redeemScript, tx, 0, SIGHASH_ALL) + # TODO: figure out how to better protect privkey + privkey = bitcoind.dumpprivkey(redeemPubKey) + sig = privkey.sign(sighash) + bytes([SIGHASH_ALL]) + print("SECRET", secret) + preimage = b(secret) + txin.scriptSig = CScript([sig, privkey.pub, preimage, OP_TRUE, zec_redeemScript]) + + print("txin.scriptSig", b2x(txin.scriptSig)) + txin_scriptPubKey = zec_redeemScript.to_p2sh_scriptPubKey() + print('Redeem txhex', b2x(tx.serialize())) + VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,)) + print("script verified, sending raw tx") + txid = bitcoind.sendrawtransaction(tx) + print("Txid of submitted redeem tx: ", b2x(lx(b2x(txid)))) + print("TXID SUCCESSFULLY REDEEMED") + return 'redeem_tx', b2x(lx(b2x(txid))) + else: + print("nLocktime exceeded, refunding") + refundPubKey = find_refundAddr(contract) + print('refundPubKey', refundPubKey) + txid = bitcoind.sendtoaddress(refundPubKey, fundtx['amount'] - FEE) + print("Txid of refund tx:", b2x(lx(b2x(txid)))) + print("TXID SUCCESSFULLY REFUNDED") + return 'refund_tx', b2x(lx(b2x(txid))) + else: + print("No contract for this p2sh found in database", p2sh) + # takes hex and returns array of decoded script op codes +# This seems to be a costly operation, minimize frequency of calls. def parse_script(script_hex): redeemScript = zcashd.decodescript(script_hex) scriptarray = redeemScript['asm'].split(' ') @@ -216,9 +282,6 @@ def find_transaction_to_address(p2sh): bitcoind.importaddress(p2sh, "", False) txs = bitcoind.listunspent() for tx in txs: - # print("tx addr:", tx['address']) - # print(type(tx['address'])) - # print(type(p2sh)) if tx['address'] == CBitcoinAddress(p2sh): print("Found tx to p2sh", p2sh) print(tx) diff --git a/cli.py b/cli.py index c1f746f..cf287b1 100644 --- a/cli.py +++ b/cli.py @@ -6,34 +6,44 @@ from trades import * from xcat import * import ast -def find_role(contract): - # Obviously when regtest created both addrs on same machine, role is both. - if parse_addrs(contract.initiator): - return 'initiator' - else: - return 'fulfiller' +def save_state(trade): + save(trade) + db.create -def parse_addrs(address): - if address[:1] == 'm': - status = bXcat.validateaddress(address) - else: - status = zXcat.validateaddress(address) - status = status['ismine'] - print("Address {0} is mine: {1}".format(address, status)) - return status - -def checkSellActions(trade): +def checkSellStatus(trade): if trade.buy.get_status() == 'funded': - seller_redeem(trade) + secret = get_secret() + print("SECRET found in checksellactions", secret) + trade = seller_redeem_p2sh(trade, secret) + print("TRADE SUCCESSFULLY REDEEMED", trade) + save_state(trade) elif trade.buy.get_status() == 'empty': print("Buyer has not yet funded the contract where you offered to buy {0}, please wait for them to complete their part.".format(trade.buy.currency)) + elif trade.buy.get_status() == 'redeemed': + print("You have already redeemed the p2sh on the second chain of this trade.") -def checkBuyActions(trade): + +def checkBuyStatus(trade): if trade.sell.get_status() == 'funded' and trade.buy.get_status() != 'redeemed': print("One active trade available, fulfilling buyer contract...") - buyer_fulfill(trade) + # they should calculate redeemScript for themselves + htlc = create_htlc(trade.buy.currency, trade.buy.fulfiller, trade.buy.initiator, trade.commitment, trade.buy.locktime) + print("Buyer p2sh:", htlc['p2sh']) + # If the two p2sh match... + if buyer_p2sh == contract.buy.p2sh: + fund_tx = fund_contract(trade.buy) + trade.buy.fund_tx = fund_tx + print("trade buy with redeemscript?", trade.buy.__dict__) + save_state(trade) + else: + print("Compiled p2sh for htlc does not match what seller sent.") elif trade.buy.get_status() == 'redeemed': - buyer_redeem(trade) + # TODO: secret parsing + # secret = parse_secret(trade.buy.currency, trade.buy.redeem_tx) + secret = get_secret() + print("Found secret", secret) + txid = auto_redeem_p2sh(trade.sell, secret) + print("TXID after buyer redeem", txid) print("XCAT trade complete!") def instantiateTrade(trade): @@ -61,7 +71,7 @@ if __name__ == '__main__': hexstr = args.argument[0] trade = x2s(hexstr) trade = instantiateTrade(ast.literal_eval(trade)) - db.create(trade) + save_state(trade) # print(trade.toJ) elif command == 'exporttrade': trade = get_trade() @@ -73,10 +83,10 @@ if __name__ == '__main__': trade = instantiateTrade(trade) if find_role(trade.sell) == 'initiator': role = 'seller' - checkSellActions(trade) + checkSellStatus(trade) else: role = 'buyer' - checkBuyActions(trade) + checkBuyStatus(trade) elif command == 'newtrade': erase_trade() role = 'seller' @@ -92,3 +102,19 @@ if __name__ == '__main__': txid = args.argument[0] trade = db.get(txid) print(x2s(b2x(trade))) + # Ad hoc testing starts here + elif command == "step1": + erase_trade() + print("Creating new XCAT trade...") + trade = seller_initiate(Trade()) + # Save it to leveldb + save_state(trade) + elif command == "step2": + trade = get_trade() + checkBuyStatus(trade) + elif command == "step3": + trade = get_trade() + checkSellStatus(trade) + elif command == "step4": + trade = get_trade() + checkBuyStatus(trade) diff --git a/database.py b/database.py index 4b3ffba..39b4422 100644 --- a/database.py +++ b/database.py @@ -8,9 +8,9 @@ db = plyvel.DB('/tmp/testdb', create_if_missing=True) trade = get_trade() ## txid we retrieve by -if trade and 'sell' in trade: - if 'fund_tx' in trade['sell']: - txid = trade['sell']['fund_tx'] +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): diff --git a/secret.json b/secret.json index 789d486..8503f44 100644 --- a/secret.json +++ b/secret.json @@ -1 +1 @@ -UYH0XxCs \ No newline at end of file +2E8ASX0w \ No newline at end of file diff --git a/trades.py b/trades.py index 9e349d8..6330baf 100644 --- a/trades.py +++ b/trades.py @@ -1,10 +1,11 @@ import json class Trade(object): - def __init__(self, sell=None, buy=None): + def __init__(self, sell=None, buy=None, commitment=None): '''Create a new trade with a sell contract and buy contract across two chains''' self.sell = sell self.buy = buy + self.commitment = commitment def toJSON(self): return json.dumps(self, default=lambda o: o.__dict__, diff --git a/xcat.json b/xcat.json index fe3cf4a..e69de29 100644 --- a/xcat.json +++ b/xcat.json @@ -1 +0,0 @@ -{"buy": {"fulfiller": "tmTjZSg4pX2Us6V5HttiwFZwj464fD2ZgpY", "initiator": "tmFRXyju7ANM7A9mg75ZjyhFW1UJEhUPwfQ", "p2sh": "t2TcYheueGfEnT2SKYMLWNXKfyzrMLKc6y2", "redeemblocknum": 113817, "currency": "zcash", "amount": 1.2, "redeemScript": "63a820b67f875a86ea6be94a1f6e44857daa739df84421ba2402dd968185b7d58371b68876a9143ea29256c9d2888ca23de42a8b8e69ca2ec235b1670399bc01b17576a914c5acca6ef39c843c7a9c3ad01b2da95fe2edf5ba6888ac"}, "sell": {"fulfiller": "mrQzUGU1dwsWRx5gsKKSDPNtrsP65vCA3Z", "initiator": "myfFr5twPYNwgeXyjCmGcrzXtCmfmWXKYp", "fund_tx": "1171aeda64eff388b3568fa4675d0ca78852911109bbe42e0ef11ad6bf1b159e", "p2sh": "2NEy1foaQU3wkMu7yygW1GZYhikeSxq6ZCq", "redeemblocknum": 911, "currency": "bitcoin", "amount": 3.5, "redeemScript": "63a820b67f875a86ea6be94a1f6e44857daa739df84421ba2402dd968185b7d58371b68876a9147788b4511a25fba1092e67b307a6dcdb6da125d967028f03b17576a914c7043e62a7391596116f54f6a64c8548e97d3fd96888ac"}} \ No newline at end of file diff --git a/xcat.py b/xcat.py index 5122e59..e2db91b 100644 --- a/xcat.py +++ b/xcat.py @@ -17,11 +17,11 @@ def check_p2sh(currency, address): print("Checking funds in Zcash p2sh") return zXcat.check_funds(address) -def create_htlc(currency, funder, redeemer, secret, locktime): +def create_htlc(currency, funder, redeemer, commitment, locktime): if currency == 'bitcoin': - sell_p2sh = bXcat.hashtimelockcontract(funder, redeemer, secret, locktime) + sell_p2sh = bXcat.hashtimelockcontract(funder, redeemer, commitment, locktime) else: - sell_p2sh = zXcat.hashtimelockcontract(funder, redeemer, secret, locktime) + sell_p2sh = zXcat.hashtimelockcontract(funder, redeemer, commitment, locktime) return sell_p2sh def fund_htlc(currency, p2sh, amount): @@ -30,12 +30,16 @@ def fund_htlc(currency, p2sh, amount): else: txid = zXcat.fund_htlc(p2sh, amount) return txid +# +# def fund_buy_contract(trade): +# buy = trade.buy +# txid = fund_htlc(buy.currency, buy.p2sh, buy.amount) +# setattr(trade.buy, 'fund_tx', txid) +# save(trade) +# return txid -def fund_buy_contract(trade): - buy = trade.buy - txid = fund_htlc(buy.currency, buy.p2sh, buy.amount) - setattr(trade.buy, 'fund_tx', txid) - save(trade) +def fund_contract(contract): + txid = fund_htlc(contract.currency, contract.p2sh, contract.amount) return txid def fund_sell_contract(trade): @@ -45,22 +49,22 @@ def fund_sell_contract(trade): save(trade) return txid -def create_sell_p2sh(trade, secret, locktime): +def create_sell_p2sh(trade, commitment, locktime): # CREATE SELL CONTRACT sell = trade.sell - contract = create_htlc(sell.currency, sell.initiator, sell.fulfiller, secret, locktime) + contract = create_htlc(sell.currency, sell.initiator, sell.fulfiller, commitment, locktime) print("sell contract", contract) setattr(trade.sell, 'p2sh', contract['p2sh']) setattr(trade.sell, 'redeemScript', contract['redeemScript']) setattr(trade.sell, 'redeemblocknum', contract['redeemblocknum']) save(trade) -def create_buy_p2sh(trade, secret, locktime): +def create_buy_p2sh(trade, commitment, locktime): ## CREATE BUY CONTRACT buy = trade.buy print("Now creating buy contract on the {0} blockchain where you will wait for the buyer to send funds...".format(buy.currency)) - print("HTLC DETAILS", buy.currency, buy.fulfiller, buy.initiator, secret, locktime) - buy_contract = create_htlc(buy.currency, buy.fulfiller, buy.initiator, secret, locktime) + print("HTLC DETAILS", buy.currency, buy.fulfiller, buy.initiator, commitment, locktime) + buy_contract = create_htlc(buy.currency, buy.fulfiller, buy.initiator, commitment, locktime) print("Buy contract", buy_contract) setattr(trade.buy, 'p2sh', buy_contract['p2sh']) @@ -70,7 +74,7 @@ def create_buy_p2sh(trade, secret, locktime): save(trade) -def redeem_p2sh(contract, secret): +def auto_redeem_p2sh(contract, secret): currency = contract.currency if currency == 'bitcoin': res = bXcat.auto_redeem(contract, secret) @@ -78,10 +82,20 @@ def redeem_p2sh(contract, secret): res = zXcat.auto_redeem(contract, secret) return res -def print_trade(role): - print("\nTrade status for {0}:".format(role)) - trade = get_trade() - pprint(trade) + +def redeem_p2sh(contract, secret): + currency = contract.currency + if currency == 'bitcoin': + res = bXcat.redeem_contract(contract, secret) + else: + res = zXcat.redeem_contract(contract, secret) + return res + +def parse_secret(chain, txid): + if chain == 'bitcoin': + secret = bXcat.parse_secret(txid) + else: + secret = zXcat.parse_secret(txid) #### Main functions determining user flow from command line def buyer_redeem(trade): @@ -104,7 +118,7 @@ def buyer_redeem(trade): save(trade) exit() -def seller_redeem(trade): +def seller_redeem_p2sh(trade, secret): buy = trade.buy userInput.authorize_seller_redeem(buy) @@ -113,12 +127,11 @@ def seller_redeem(trade): exit() else: # Seller redeems buyer's funded tx (contract in p2sh) - secret = userInput.retrieve_password() tx_type, txid = redeem_p2sh(trade.buy, secret) + print("Setting tx_type: txid", tx_type, txid) setattr(trade.buy, tx_type, txid) - save(trade) print("You have redeemed {0} {1}!".format(buy.amount, buy.currency)) - print_trade('seller') + return trade def buyer_fulfill(trade): buy = trade.buy @@ -157,11 +170,13 @@ def seller_initiate(trade): print(trade.buy.__dict__) secret = userInput.create_password() + save_secret(secret) + hash_of_secret = sha256(secret) # TODO: Implement locktimes and mock block passage of time sell_locktime = 5 buy_locktime = 10 # Must be more than first tx print("Creating pay-to-script-hash for sell contract...") - create_sell_p2sh(trade, secret, sell_locktime) + create_sell_p2sh(trade, hash_of_secret, sell_locktime) userInput.authorize_fund_sell(trade) @@ -170,68 +185,5 @@ def seller_initiate(trade): create_buy_p2sh(trade, secret, buy_locktime) + trade.commitment = b2x(hash_of_secret) return trade - -if __name__ == '__main__': - print("ZEC <-> BTC XCAT (Cross-Chain Atomic Transactions)") - print("=" * 50) - - trade = get_trade() - - if trade == None: - htlcTrade = Trade() - print("New empty trade") - else: - buy = Contract(trade['buy']) - sell = Contract(trade['sell']) - htlcTrade = Trade(buy=buy, sell=sell) - - try: - if sys.argv[1] == 'new': - erase_trade() - role = 'seller' - htlcTrade = Trade() - print("Creating new XCAT transaction...") - else: - 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 htlcTrade.buy is not None and htlcTrade.sell is not None: - if htlcTrade.sell.get_status() == 'redeemed' and htlcTrade.buy.get_status() == 'redeemed': - print("This trade is already complete! Trade details:") - pprint(trade) - exit() - - if role == "seller": - if htlcTrade.sell == None: - seller_initiate(htlcTrade) - elif htlcTrade.buy.get_status() == 'funded': - seller_redeem(htlcTrade) - elif htlcTrade.buy.get_status() == 'empty': - print("Buyer has not yet funded the contract where you offered to buy {0}, please wait for them to complete their part.".format(htlcTrade.buy.currency)) - else: - # Need better way of preventing buyer from having secret - # if 'status' not in trade['buy'] and trade['sell']['status'] == 'funded': - if htlcTrade.sell.get_status() == 'funded' and htlcTrade.buy.get_status() != 'redeemed': - print("One active trade available, fulfilling buyer contract...") - buyer_fulfill(htlcTrade) - # How to monitor if txs are included in blocks -- should use blocknotify and a monitor daemon? - # p2sh = trade['buy']['p2sh'] - # check_blocks(p2sh) - elif htlcTrade.buy.get_status() == 'redeemed': - # Seller has redeemed buyer's tx, buyer can now redeem. - buyer_redeem(htlcTrade) - print("XCAT trade complete!") - - # Note: there is some little endian weirdness in the bXcat and zXcat files, need to handle the endianness of txids better & more consistently diff --git a/zXcat.py b/zXcat.py index 2d8eebd..0f844c8 100644 --- a/zXcat.py +++ b/zXcat.py @@ -36,16 +36,16 @@ def get_keys(funder_address, redeemer_address): def privkey(address): zcashd.dumpprivkey(address) -def hashtimelockcontract(funder, redeemer, secret, locktime): +def hashtimelockcontract(funder, redeemer, commitment, locktime): funderAddr = CBitcoinAddress(funder) redeemerAddr = CBitcoinAddress(redeemer) - h = sha256(secret) + # h = sha256(secret) blocknum = zcashd.getblockcount() print("Current blocknum", blocknum) redeemblocknum = blocknum + locktime print("REDEEMBLOCKNUM ZCASH", redeemblocknum) # can rm op_dup and op_hash160 if you replace addrs with pubkeys (as raw hex/bin data?), and can rm last op_equalverify (for direct pubkey comparison) - zec_redeemScript = CScript([OP_IF, OP_SHA256, h, OP_EQUALVERIFY,OP_DUP, OP_HASH160, + zec_redeemScript = CScript([OP_IF, OP_SHA256, x(commitment), 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("Redeem script for p2sh contract on Zcash blockchain:", b2x(zec_redeemScript)) @@ -77,7 +77,7 @@ def get_tx_details(txid): def find_transaction_to_address(p2sh): zcashd.importaddress(p2sh, "", False) - txs = zcashd.listunspent() + txs = zcashd.listunspent(0, 100) for tx in txs: # print("tx addr:", tx['address']) # print(type(tx['address'])) @@ -128,7 +128,6 @@ def parse_secret(txid): # redeems automatically after buyer has funded tx, by scanning for transaction to the p2sh # i.e., doesn't require buyer telling us fund txid - def auto_redeem(contract, secret): # How to find redeemScript and redeemblocknum from blockchain? print("Contract in auto redeem", contract.__dict__) @@ -187,13 +186,74 @@ def auto_redeem(contract, secret): else: print("No contract for this p2sh found in database", p2sh) +def redeem_contract(contract, secret): + # How to find redeemScript and redeemblocknum from blockchain? + print("Contract in redeem contract", contract.__dict__) + p2sh = contract.p2sh + #checking there are funds in the address + amount = check_funds(p2sh) + if(amount == 0): + print("address ", p2sh, " not funded") + quit() + fundtx = find_transaction_to_address(p2sh) + amount = fundtx['amount'] / COIN + print("Found fundtx:", fundtx) + p2sh = P2SHBitcoinAddress(p2sh) + if fundtx['address'] == p2sh: + print("Found {0} in p2sh {1}, redeeming...".format(amount, p2sh)) + + # Where can you find redeemblocknum in the transaction? + # redeemblocknum = find_redeemblocknum(contract) + blockcount = zcashd.getblockcount() + print("\nCurrent blocknum at time of redeem on Zcash:", blockcount) + if blockcount < contract.d: + # TODO: parse the script once, up front. + redeemPubKey = find_redeemAddr(contract) + + + print('redeemPubKey', redeemPubKey) + zec_redeemScript = CScript(x(contract.redeemScript)) + txin = CMutableTxIn(fundtx['outpoint']) + txout = CMutableTxOut(fundtx['amount'] - FEE, redeemPubKey.to_scriptPubKey()) + # Create the unsigned raw transaction. + tx = CMutableTransaction([txin], [txout]) + sighash = SignatureHash(zec_redeemScript, tx, 0, SIGHASH_ALL) + # TODO: figure out how to better protect privkey + privkey = zcashd.dumpprivkey(redeemPubKey) + sig = privkey.sign(sighash) + bytes([SIGHASH_ALL]) + print("SECRET", secret) + preimage = secret.encode('utf-8') + txin.scriptSig = CScript([sig, privkey.pub, preimage, OP_TRUE, zec_redeemScript]) + + print("txin.scriptSig", b2x(txin.scriptSig)) + txin_scriptPubKey = zec_redeemScript.to_p2sh_scriptPubKey() + print('Redeem txhex', b2x(tx.serialize())) + VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,)) + print("script verified, sending raw tx") + txid = zcashd.sendrawtransaction(tx) + print("Txid of submitted redeem tx: ", b2x(lx(b2x(txid)))) + print("TXID SUCCESSFULLY REDEEMED") + return 'redeem_tx', b2x(lx(b2x(txid))) + else: + print("nLocktime exceeded, refunding") + refundPubKey = find_refundAddr(contract) + print('refundPubKey', refundPubKey) + txid = zcashd.sendtoaddress(refundPubKey, fundtx['amount'] - FEE) + print("Txid of refund tx:", b2x(lx(b2x(txid)))) + print("TXID SUCCESSFULLY REFUNDED") + return 'refund_tx', b2x(lx(b2x(txid))) + else: + print("No contract for this p2sh found in database", p2sh) + def parse_script(script_hex): redeemScript = zcashd.decodescript(script_hex) scriptarray = redeemScript['asm'].split(' ') return scriptarray def find_redeemblocknum(contract): + print("In find_redeemblocknum") scriptarray = parse_script(contract.redeemScript) + print("Returning scriptarray", scriptarray) redeemblocknum = scriptarray[8] return int(redeemblocknum)