redeem with secret works

This commit is contained in:
Ariel Gabizon 2017-07-03 18:38:34 +02:00
parent 3a836cf4f5
commit d5821f5ca7
6 changed files with 289 additions and 81 deletions

129
bXcat.py
View File

@ -66,6 +66,7 @@ def fund_htlc(p2sh, amount):
send_amount = float(amount) * COIN
fund_txid = bitcoind.sendtoaddress(p2sh, send_amount)
txid = b2x(lx(b2x(fund_txid)))
print("funding btc sell address:", txid)
return txid
def check_funds(p2sh):
@ -73,6 +74,7 @@ def check_funds(p2sh):
# Get amount in address
amount = bitcoind.getreceivedbyaddress(p2sh, 0)
amount = amount/COIN
print("Amount in bitcoin address ", p2sh, ":",amount)
return amount
## TODO: FIX search for p2sh in block
@ -102,17 +104,19 @@ def get_tx_details(txid):
fund_txinfo = bitcoind.gettransaction(lx(txid))
return fund_txinfo['details'][0]
# redeems automatically after buyer has funded tx, by scanning for transaction to the p2sh
# redeems funded tx automatically, by scanning for transaction to the p2sh
# i.e., doesn't require buyer telling us fund txid
def auto_redeem(contract, secret):
# returns false if fund tx doesn't exist or is too small
def redeem_with_secret(contract, secret):
# How to find redeemScript and redeemblocknum from blockchain?
print("Contract in auto redeem", contract.__dict__)
print("Redeeming contract using secret", contract.__dict__)
p2sh = contract.p2sh
minamount = float(contract.amount)
#checking there are funds in the address
amount = check_funds(p2sh)
if(amount == 0):
print("address ", p2sh, " not funded")
quit()
if(amount < minamount):
print("address ", p2sh, " not sufficiently funded")
return false
fundtx = find_transaction_to_address(p2sh)
amount = fundtx['amount'] / COIN
print("Found fundtx:", fundtx)
@ -120,43 +124,26 @@ def auto_redeem(contract, secret):
if fundtx['address'] == p2sh:
print("Found {0} in p2sh {1}, redeeming...".format(amount, p2sh))
# Parsing redeemblocknum from the redeemscript of the p2sh
redeemblocknum = find_redeemblocknum(contract)
blockcount = bitcoind.getblockcount()
print("\nCurrent blocknum at time of redeem on Bitcoin:", blockcount)
if blockcount < redeemblocknum:
redeemPubKey = find_redeemAddr(contract)
print('redeemPubKey', redeemPubKey)
else:
print("nLocktime exceeded, refunding")
redeemPubKey = find_refundAddr(contract)
print('refundPubKey', redeemPubKey)
# redeemPubKey = CBitcoinAddress.from_scriptPubKey(redeemPubKey)
# exit()
redeemPubKey = find_redeemAddr(contract)
print('redeemPubKey', redeemPubKey)
zec_redeemScript = CScript(x(contract.redeemScript))
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])
# nLockTime needs to be at least as large as parameter of CHECKLOCKTIMEVERIFY for script to verify
# TODO: these things like redeemblocknum should really be properties of a tx class...
# Need: redeemblocknum, zec_redeemScript, secret (for creator...), txid, redeemer...
if blockcount >= redeemblocknum:
print("\nLocktime exceeded")
tx.nLockTime = redeemblocknum
sighash = SignatureHash(zec_redeemScript, tx, 0, SIGHASH_ALL)
sighash = SignatureHash(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 = secret.encode('utf-8')
txin.scriptSig = CScript([sig, privkey.pub, preimage, OP_TRUE, zec_redeemScript])
txin.scriptSig = CScript([sig, privkey.pub, preimage, OP_TRUE, redeemScript])
# exit()
print("txin.scriptSig", b2x(txin.scriptSig))
txin_scriptPubKey = zec_redeemScript.to_p2sh_scriptPubKey()
txin_scriptPubKey = 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")
@ -166,6 +153,69 @@ def auto_redeem(contract, secret):
else:
print("No contract for this p2sh found in database", p2sh)
# given a contract return true or false according to whether the relevant fund tx's timelock is still valid
def still_locked(contract):
p2sh = contract.p2sh
# Parsing redeemblocknum from the redeemscript of the p2sh
redeemblocknum = find_redeemblocknum(contract)
blockcount = bitcoind.getblockcount()
print(blockcount, redeemblocknum, blockcount<redeemblocknum)
return (int(blockcount) < int(redeemblocknum))
def redeem_after_timelock(contract):
print("Contract in auto redeem", contract.__dict__)
p2sh = contract.p2sh
fundtx = find_transaction_to_address(p2sh)
amount = fundtx['amount'] / COIN
if (fundtx['address'].__str__() != p2sh):
print("no fund transaction found to the contract p2sh address ",p2sh)
quit()
print("Found fundtx:", fundtx)
# Parsing redeemblocknum from the redeemscript of the p2sh
redeemblocknum = find_redeemblocknum(contract)
blockcount = bitcoind.getblockcount()
print ("Current block:", blockcount, "Can redeem from block:", redeemblocknum)
if(still_locked(contract)):
print("too early for redeeming with timelock")
quit()
print("Found {0} in p2sh {1}, redeeming...".format(amount, p2sh))
redeemPubKey = find_refundAddr(contract)
print('refundPubKey', redeemPubKey)
redeemScript = CScript(x(contract.redeemScript))
txin = CMutableTxIn(fundtx['outpoint'])
txout = CMutableTxOut(fundtx['amount'] - FEE, redeemPubKey.to_scriptPubKey())
# Create the unsigned raw transaction.
txin.nSequence = 0
tx = CMutableTransaction([txin], [txout])
tx.nLockTime = redeemblocknum
sighash = SignatureHash(redeemScript, tx, 0, SIGHASH_ALL)
# TODO: figure out how to better protect privkey
privkey = bitcoind.dumpprivkey(redeemPubKey)
sig = privkey.sign(sighash) + bytes([SIGHASH_ALL])
txin.scriptSig = CScript([sig, privkey.pub, OP_FALSE, redeemScript])
# exit()
print("txin.scriptSig", b2x(txin.scriptSig))
txin_scriptPubKey = 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))))
return b2x(lx(b2x(txid)))
# takes hex and returns array of decoded script op codes
def parse_script(script_hex):
redeemScript = zcashd.decodescript(script_hex)
@ -223,9 +273,26 @@ def find_transaction_to_address(p2sh):
def new_bitcoin_addr():
addr = bitcoind.getnewaddress()
print('new btc addr', addr.to_scriptPubKey)
return addr.to_scriptPubKey()
print('new btc addr', addr)
return addr
def generate(num):
blocks = bitcoind.generate(num)
return blocks
def find_secret(p2sh):
bitcoind.importaddress(p2sh, "", False)
# is this working?
txs = bitcoind.listtransactions()
for tx in txs:
# print("tx addr:", tx['address'])
# print(type(tx['address']))
# print(type(p2sh))
if (tx['address'] == p2sh ) and (tx['category'] == "send"):
print(type(tx['txid']))
print(str.encode(tx['txid']))
raw = bitcoind.getrawtransaction(lx(tx['txid']),True)['hex']
decoded = bitcoind.decoderawtransaction(raw)
secret = decoded['vin'][0]['scriptSig']['asm']
print("secret:", secret)
return secret

View File

@ -1 +1 @@
9NulTQVe
wfP4CYjl

65
test.py
View File

@ -6,10 +6,19 @@ htlcTrade = Trade()
print("Starting test of xcat...")
def get_initiator_addresses():
return {'bitcoin': 'myfFr5twPYNwgeXyjCmGcrzXtCmfmWXKYp', 'zcash': 'tmFRXyju7ANM7A9mg75ZjyhFW1UJEhUPwfQ'}
baddr = bXcat.new_bitcoin_addr()
zaddr = zXcat.new_zcash_addr()
# print("type baddr", type(baddr))
# print("type baddr", type(baddr.to_scriptPubKey()))
return {'bitcoin': baddr.__str__(), 'zcash': zaddr.__str__()}
# return {'bitcoin': 'myfFr5twPYNwgeXyjCmGcrzXtCmfmWXKYp', 'zcash': 'tmFRXyju7ANM7A9mg75ZjyhFW1UJEhUPwfQ'}
def get_fulfiller_addresses():
return {'bitcoin': 'mrQzUGU1dwsWRx5gsKKSDPNtrsP65vCA3Z', 'zcash': 'tmTjZSg4pX2Us6V5HttiwFZwj464fD2ZgpY'}
baddr = bXcat.new_bitcoin_addr()
zaddr = zXcat.new_zcash_addr()
return {'bitcoin': baddr.__str__(), 'zcash': zaddr.__str__()}
# return {'bitcoin': 'myfFr5twPYNwgeXyjCmGcrzXtCmfmWXKYp', 'zcash': 'tmFRXyju7ANM7A9mg75ZjyhFW1UJEhUPwfQ'}
# return {'bitcoin': 'mrQzUGU1dwsWRx5gsKKSDPNtrsP65vCA3Z', 'zcash': 'tmTjZSg4pX2Us6V5HttiwFZwj464fD2ZgpY'}
def initiate(trade):
# Get amounts
@ -43,33 +52,38 @@ def initiate(trade):
print("Sent")
create_buy_p2sh(trade, secret, buy_locktime)
def fulfill(trade):
# buyer checks that seller funded the sell contract, and if so funds the buy contract
def buyer_fulfill(trade):
print("BUYER FULFILL")
print("=============")
buy = trade.buyContract
sell = trade.sellContract
buy_p2sh_balance = check_p2sh(buy.currency, buy.p2sh)
# buy_p2sh_balance = check_p2sh(buy.currency, buy.p2sh)
sell_p2sh_balance = check_p2sh(sell.currency, sell.p2sh)
if (sell_p2sh_balance < float(sell.amount)):
raise ValueError("Sell p2sh not funded, buyer cannot redeem")
print("Seller has deposited funds, so funding the buy contract:")
txid = fund_buy_contract(trade)
print("Buyer Fund tx txid:", txid)
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):
def redeem_seller(trade):
print("SELLER REDEEMING BUY CONTRACT")
print("=============================")
buy = trade.buyContract
if trade.sellContract.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.buyContract, secret)
print("\nTX Type", tx_type)
setattr(trade.buyContract, tx_type, txid)
secret = get_secret() # Just the seller getting his local copy of the secret
print("SELLER SECRET IN TEST:", secret)
txid = redeem_p2sh(trade.buyContract, secret, trade.sellContract)
setattr(trade.buyContract, 'redeem_tx', txid)
save(trade)
print("You have redeemed {0} {1}!".format(buy.amount, buy.currency))
def redeem_two(trade):
def redeem_buyer(trade):
print("BUYER REDEEMING SELL CONTRACT")
print("=============================")
if trade.sellContract.get_status() == 'redeemed':
raise RuntimeError("Sell contract was redeemed before buyer could retrieve funds")
elif trade.buyContract.get_status() == 'refunded':
@ -77,11 +91,11 @@ def redeem_two(trade):
else:
# Buy contract is where seller disclosed secret in redeeming
if trade.buyContract.currency == 'bitcoin':
secret = bXcat.parse_secret(trade.buyContract.redeem_tx)
secret = bXcat.find_secret(trade.buyContract.p2sh,trade.buyContract.fund_tx)
else:
secret = zXcat.parse_secret(trade.buyContract.redeem_tx)
secret = zXcat.find_secret(trade.buyContract.p2sh,trade.buyContract.fund_tx)
print("Found secret in seller's redeem tx", secret)
redeem_tx = redeem_p2sh(trade.sellContract, secret)
redeem_tx = redeem_p2sh(trade.sellContract, secret, trade.buyContract)
setattr(trade.sellContract, 'redeem_tx', redeem_tx)
save(trade)
@ -90,12 +104,11 @@ def generate_blocks(num):
zXcat.generate(num)
initiate(htlcTrade)
fulfill(htlcTrade)
buyer_fulfill(htlcTrade)
generate_blocks(6)
redeem_one(htlcTrade)
redeem_two(htlcTrade)
# generate_blocks(12)
redeem_seller(htlcTrade)
redeem_buyer(htlcTrade)
# addr = CBitcoinAddress('tmFRXyju7ANM7A9mg75ZjyhFW1UJEhUPwfQ')
# print(addr)

View File

@ -1 +1 @@
{"sell": {"currency": "bitcoin", "p2sh": "2NGSX1vKsbUoNYusifWXStb1QBRmsh4KYte", "redeemblocknum": 6482, "amount": "0.5", "redeemScript": "63a820dc1abac5a0994304dffd84e49e4a0b9d65decf323025d634d0b01e48b8b444558876a9147788b4511a25fba1092e67b307a6dcdb6da125d967025219b17576a914c7043e62a7391596116f54f6a64c8548e97d3fd96888ac", "fulfiller": "mrQzUGU1dwsWRx5gsKKSDPNtrsP65vCA3Z", "initiator": "myfFr5twPYNwgeXyjCmGcrzXtCmfmWXKYp", "fund_tx": "70df04f83baeb3fc626f721945712f39eacfa72f60cc416ea07e692bb2b08c36"}, "buy": {"currency": "zcash", "p2sh": "t27J7ZQYmbu8AVxTEMkDE92JTPoA1kag3hV", "redeemblocknum": 646, "amount": "1.12", "redeemScript": "63a820dc1abac5a0994304dffd84e49e4a0b9d65decf323025d634d0b01e48b8b444558876a9143ea29256c9d2888ca23de42a8b8e69ca2ec235b167028602b17576a914c5acca6ef39c843c7a9c3ad01b2da95fe2edf5ba6888ac", "refund_tx": "8ace9f4ea8fbc570147b134fc7eda8448396bf19453e704315ed97bbff947d59", "fulfiller": "tmTjZSg4pX2Us6V5HttiwFZwj464fD2ZgpY", "initiator": "tmFRXyju7ANM7A9mg75ZjyhFW1UJEhUPwfQ", "fund_tx": "1af049328d793c616862b0946e14e998966d16e8102726a0252d41db992095cd"}}
{"sell": {"redeemblocknum": 7118, "redeem_tx": "707015331518425a82672ae90ab1a04dd482be485961ba150895479f48aafb41", "redeemScript": "63a8201f6c4e355816e9660f156acd281f3e2dc3d71d4da1fe63560ef7b68b2384a9f08876a91447c15e08aa91bd2cb9ab48bd22c14a0bcdcc635d6702ce1bb17576a914ce26fe4177ea51f9ac1606f6558d6b1d3c6753a56888ac", "fulfiller": "mn4Mv54k2Pem7KfCdpuv6rRX3SUUqUMHdE", "initiator": "mzJzCs8ikH9zf9o7WPBfyi7tjuyPwuFfsF", "amount": "0.5", "currency": "bitcoin", "fund_tx": "3751cd28a7db614417d88462931d355552006074922f48c2b723d05a49f5ea9f", "p2sh": "2N6xFjJvP693JyaY9tVendhiQHgFEwarzbV"}, "buy": {"redeemblocknum": 1284, "redeem_tx": "837445320d9ad9e329f35a293d9f105af62a749b052936d77951491ac4b314dd", "redeemScript": "63a8201f6c4e355816e9660f156acd281f3e2dc3d71d4da1fe63560ef7b68b2384a9f08876a914f1fcc37118dc3cba7988dcad373139bdee70f33b67020405b17576a914a4424b672dd9656f439a113cd29479ed8f5cf1c76888ac", "fulfiller": "tmQgsZrgZuGb1CRxd2qTRW93Ppec1JNf9fX", "initiator": "tmXmryiQfjvbgZ5C3cjbDtzisAmyMuTpqkY", "amount": "1.12", "currency": "zcash", "fund_tx": "26a10d06edc78a5d57510e990971f1a3b44a1217b42b74881230c0f374781efc", "p2sh": "t2DBJ2JdWhcakL4LHz4uyeb9jpTGuBHQDBR"}}

21
xcat.py
View File

@ -70,14 +70,25 @@ def create_buy_p2sh(trade, secret, locktime):
save(trade)
def redeem_p2sh(contract, secret):
# we try to redeem contract with secret
# we try to redeem revertcontract with time lock
def redeem_p2sh(contract, secret, revertcontract):
currency = contract.currency
print("in redeem function zcash")
if currency == 'bitcoin':
res = bXcat.auto_redeem(contract, secret)
if(bXcat.still_locked(contract)):
print("redeeming btc with secret:")
res = bXcat.redeem_with_secret(contract, secret)
else:
print("redeeming zec with timelock:")
res = zXcat.redeem_after_timelock(revertcontract)
else:
res = zXcat.auto_redeem(contract, secret)
print("in redeem function zcash")
if(zXcat.still_locked(contract)):
print("redeeming zec with secret:")
res = zXcat.redeem_with_secret(contract, secret)
else:
print("redeeming btc with timelock:")
res = bXcat.redeem_after_timelock(revertcontract)
return res

151
zXcat.py
View File

@ -60,9 +60,10 @@ def fund_htlc(p2sh, amount):
return txid
def check_funds(p2sh):
zcashd.importaddress(p2sh, "", True) #Ariel: changed this to true
zcashd.importaddress(p2sh, "", False) #Ariel: changed this to true
print("Imported address", p2sh)
# Get amount in address
print("findtxtoaddr:::::::", find_transaction_to_address(p2sh))
amount = zcashd.getreceivedbyaddress(p2sh, 0)
print("Amount in address", amount)
amount = amount/COIN
@ -93,24 +94,28 @@ def find_transaction_to_address(p2sh):
#
# return fund_txinfo['details'][0]
def find_secret(p2sh):
return parse_secret('4c25b5db9f3df48e48306891d8437c69308afa122f92416df1a3ba0d3604882f')
zcashd.importaddress(p2sh, "", False)
def find_secret(p2sh,vinid):
zcashd.importaddress(p2sh, "", True)
# is this working?
txs = zcashd.listtransactions()
for tx in txs:
# print("tx addr:", tx['address'])
print("tx addr:", tx['txid'])
# print(type(tx['address']))
# print(type(p2sh))
if (tx['address'] == p2sh ) and (tx['category'] == "send"):
print(type(tx['txid']))
print(str.encode(tx['txid']))
raw = zcashd.getrawtransaction(lx(tx['txid']),True)['hex']
decoded = zcashd.decoderawtransaction(raw)
print("deo:", decoded['vin'][0]['scriptSig']['asm'])
raw = zcashd.getrawtransaction(lx(tx['txid']),True)['hex']
decoded = zcashd.decoderawtransaction(raw)
print("fdsfdfds", decoded['vin'][0])
if('txid' in decoded['vin'][0]):
sendid = decoded['vin'][0]['txid']
print("sendid:", sendid)
if (sendid == vinid ):
print(type(tx['txid']))
print(str.encode(tx['txid']))
return parse_secret(lx(tx['txid']))
def parse_secret(txid):
raw = zcashd.gettransaction(lx(txid), True)['hex']
raw = zcashd.gettransaction(txid, True)['hex']
# print("Raw", raw)
decoded = zcashd.decoderawtransaction(raw)
scriptSig = decoded['vin'][0]['scriptSig']
@ -144,8 +149,8 @@ def auto_redeem(contract, secret):
# Parsing redeemblocknum from the redeemscript of the p2sh
redeemblocknum = find_redeemblocknum(contract)
blockcount = bitcoind.getblockcount()
print("\nCurrent blocknum at time of redeem on Bitcoin:", blockcount)
blockcount = zcashd.getblockcount()
print("\nCurrent blocknum at time of redeem on Zcash chain:", blockcount)
if blockcount < redeemblocknum:
redeemPubKey = find_redeemAddr(contract)
print('redeemPubKey', redeemPubKey)
@ -169,7 +174,7 @@ def auto_redeem(contract, secret):
tx.nLockTime = redeemblocknum
sighash = SignatureHash(zec_redeemScript, tx, 0, SIGHASH_ALL)
# TODO: figure out how to better protect privkey
privkey = bitcoind.dumpprivkey(redeemPubKey)
privkey = zcashd.dumpprivkey(redeemPubKey)
sig = privkey.sign(sighash) + bytes([SIGHASH_ALL])
print("SECRET", secret)
preimage = secret.encode('utf-8')
@ -235,9 +240,121 @@ def find_recipient(contract):
def new_zcash_addr():
addr = zcashd.getnewaddress()
print('new ZEC addr', addr.to_p2sh_scriptPubKey)
return addr.to_scriptPubKey()
print('new ZEC addr', addr)
return addr
def generate(num):
blocks = zcashd.generate(num)
return blocks
# redeems funded tx automatically, by scanning for transaction to the p2sh
# i.e., doesn't require buyer telling us fund txid
# returns false if fund tx doesn't exist or is too small
def redeem_with_secret(contract, secret):
# How to find redeemScript and redeemblocknum from blockchain?
print("Redeeming contract using secret", contract.__dict__)
p2sh = contract.p2sh
minamount = float(contract.amount)
#checking there are funds in the address
amount = check_funds(p2sh)
if(amount < minamount):
print("address ", p2sh, " not sufficiently funded")
return false
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))
redeemPubKey = find_redeemAddr(contract)
print('redeemPubKey', redeemPubKey)
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(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, redeemScript])
# exit()
print("txin.scriptSig", b2x(txin.scriptSig))
txin_scriptPubKey = 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))))
return b2x(lx(b2x(txid)))
else:
print("No contract for this p2sh found in database", p2sh)
# given a contract return true or false according to whether the relevant fund tx's timelock is still valid
def still_locked(contract):
p2sh = contract.p2sh
# Parsing redeemblocknum from the redeemscript of the p2sh
redeemblocknum = find_redeemblocknum(contract)
blockcount = zcashd.getblockcount()
print(blockcount, redeemblocknum, blockcount<redeemblocknum)
return (int(blockcount) < int(redeemblocknum))
def redeem_after_timelock(contract):
print("Contract in auto redeem", contract.__dict__)
p2sh = contract.p2sh
fundtx = find_transaction_to_address(p2sh)
amount = fundtx['amount'] / COIN
if (fundtx['address'].__str__() != p2sh):
print("no fund transaction found to the contract p2sh address ",p2sh)
quit()
print("Found fundtx:", fundtx)
# Parsing redeemblocknum from the redeemscript of the p2sh
redeemblocknum = find_redeemblocknum(contract)
blockcount = zcashd.getblockcount()
print ("Current block:", blockcount, "Can redeem from block:", redeemblocknum)
if(still_locked(contract)):
print("too early for redeeming with timelock")
quit()
print("Found {0} in p2sh {1}, redeeming...".format(amount, p2sh))
redeemPubKey = find_refundAddr(contract)
print('refundPubKey', redeemPubKey)
redeemScript = CScript(x(contract.redeemScript))
txin = CMutableTxIn(fundtx['outpoint'])
txout = CMutableTxOut(fundtx['amount'] - FEE, redeemPubKey.to_scriptPubKey())
# Create the unsigned raw transaction.
txin.nSequence = 0
tx = CMutableTransaction([txin], [txout])
tx.nLockTime = redeemblocknum
sighash = SignatureHash(redeemScript, tx, 0, SIGHASH_ALL)
# TODO: figure out how to better protect privkey
privkey = zcashd.dumpprivkey(redeemPubKey)
sig = privkey.sign(sighash) + bytes([SIGHASH_ALL])
txin.scriptSig = CScript([sig, privkey.pub, OP_FALSE, redeemScript])
# exit()
print("txin.scriptSig", b2x(txin.scriptSig))
txin_scriptPubKey = 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))))
return b2x(lx(b2x(txid)))