redeem with secret works
This commit is contained in:
parent
3a836cf4f5
commit
d5821f5ca7
129
bXcat.py
129
bXcat.py
|
@ -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
|
||||
|
|
|
@ -1 +1 @@
|
|||
9NulTQVe
|
||||
wfP4CYjl
|
65
test.py
65
test.py
|
@ -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)
|
||||
|
|
|
@ -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
21
xcat.py
|
@ -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
151
zXcat.py
|
@ -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)))
|
||||
|
|
Loading…
Reference in New Issue