Debug checklocktimeverify process, not complete

This commit is contained in:
Jay Graber 2017-09-08 14:24:12 -07:00
parent 16826db42b
commit 59c2a1c37b
4 changed files with 152 additions and 29 deletions

View File

@ -10,7 +10,7 @@ import bitcoin.rpc
from bitcoin import SelectParams
from bitcoin.core import b2x, lx, b2lx, x, COIN, COutPoint, CMutableTxOut, CMutableTxIn, CMutableTransaction, Hash160, CTransaction
from bitcoin.base58 import decode
from bitcoin.core.script import CScript, OP_DUP, OP_IF, OP_ELSE, OP_ENDIF, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG, SignatureHash, SIGHASH_ALL, OP_FALSE, OP_DROP, OP_CHECKLOCKTIMEVERIFY, OP_SHA256, OP_TRUE
from bitcoin.core.script import CScript, OP_DUP, OP_IF, OP_ELSE, OP_ENDIF, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG, SignatureHash, SIGHASH_ALL, OP_FALSE, OP_DROP, OP_CHECKLOCKTIMEVERIFY, OP_SHA256, OP_TRUE, OP_FALSE
from bitcoin.core.scripteval import VerifyScript, SCRIPT_VERIFY_P2SH
from bitcoin.wallet import CBitcoinAddress, CBitcoinSecret, P2SHBitcoinAddress, P2PKHBitcoinAddress
@ -147,7 +147,7 @@ class bitcoinProxy():
print("Parsing script for redeem_contract...")
scriptarray = self.parse_script(contract.redeemScript)
redeemblocknum = scriptarray[8]
redeemPubKey = P2PKHBitcoinAddress.from_bytes(x(scriptarray[6]))
self.redeemPubKey = P2PKHBitcoinAddress.from_bytes(x(scriptarray[6]))
refundPubKey = P2PKHBitcoinAddress.from_bytes(x(scriptarray[13]))
p2sh = contract.p2sh
#checking there are funds in the address
@ -172,22 +172,23 @@ class bitcoinProxy():
else:
print("No contract for this p2sh found in database", p2sh)
def redeem(self, contract):
print('redeemPubKey', redeemPubKey)
zec_redeemScript = CScript(x(contract.redeemScript))
def redeem(self, contract, fundtx, secret):
print('redeemPubKey', self.redeemPubKey)
# TODO: Compare with script on blockchain?
redeemScript = CScript(x(contract.redeemScript))
txin = CMutableTxIn(fundtx['outpoint'])
txout = CMutableTxOut(fundtx['amount'] - FEE, redeemPubKey.to_scriptPubKey())
txout = CMutableTxOut(fundtx['amount'] - FEE, self.redeemPubKey.to_scriptPubKey())
# Create the unsigned raw transaction.
tx = CMutableTransaction([txin], [txout])
sighash = SignatureHash(zec_redeemScript, tx, 0, SIGHASH_ALL)
sighash = SignatureHash(redeemScript, tx, 0, SIGHASH_ALL)
# TODO: protect privkey better, separate signing from rawtx creation
privkey = self.bitcoind.dumpprivkey(redeemPubKey)
privkey = self.bitcoind.dumpprivkey(self.redeemPubKey)
sig = privkey.sign(sighash) + bytes([SIGHASH_ALL])
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])
# print("txin.scriptSig", b2x(txin.scriptSig))
txin_scriptPubKey = zec_redeemScript.to_p2sh_scriptPubKey()
txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey()
print('Raw redeem transaction hex: ', b2x(tx.serialize()))
VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,))
print("Script verified, sending raw transaction...")
@ -198,11 +199,32 @@ class bitcoinProxy():
def refund(self, contract):
fundtx = self.find_transaction_to_address(contract.p2sh)
# Refund self on other chain
print("Fund tx found in refund: ", fundtx)
refundPubKey = self.find_refundAddr(contract)
logging.debug('refundPubKey: {0}'.format(refundPubKey))
txid = self.bitcoind.sendtoaddress(refundPubKey, fundtx['amount'] - FEE)
refund_tx = b2x(lx(b2x(txid)))
print('refundPubKey: {0}'.format(refundPubKey))
redeemScript = CScript(x(contract.redeemScript))
txin = CMutableTxIn(fundtx['outpoint'])
txout = CMutableTxOut(fundtx['amount'] - FEE, refundPubKey.to_scriptPubKey())
# Create the unsigned raw transaction.
tx = CMutableTransaction([txin], [txout])
tx.nLockTime = 2430
sighash = SignatureHash(redeemScript, tx, 0, SIGHASH_ALL)
privkey = self.bitcoind.dumpprivkey(refundPubKey)
sig = privkey.sign(sighash) + bytes([SIGHASH_ALL])
# Sign without secret
# OP_IF, OP_SHA256, 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
txin.scriptSig = CScript([sig, privkey.pub, OP_FALSE, redeemScript])
# txin.nSequence = 2185
txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey()
print('Raw redeem transaction hex: {0}'.format(b2x(tx.serialize())))
res = VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,))
print("Script verified, sending raw transaction... (NOT)", res)
txid = self.bitcoind.sendrawtransaction(tx)
refund_tx = b2x(lx(b2x(txid)))
fund_tx = str(fundtx['outpoint'])
return {"refund_tx": refund_tx, "fund_tx": fund_tx}

View File

@ -0,0 +1,83 @@
#!/usr/bin/env python3
import sys
if sys.version_info.major < 3:
sys.stderr.write('Sorry, Python 3.x required by this example.\n')
sys.exit(1)
import bitcoin
import bitcoin.rpc
from bitcoin import SelectParams
from bitcoin.core import b2x, lx, b2lx, x, COIN, COutPoint, CMutableTxOut, CMutableTxIn, CMutableTransaction, Hash160, CTransaction
from bitcoin.base58 import decode
from bitcoin.core.script import CScript, OP_DUP, OP_IF, OP_ELSE, OP_ENDIF, OP_HASH160, OP_EQUALVERIFY, OP_CHECKSIG, SignatureHash, SIGHASH_ALL, OP_FALSE, OP_DROP, OP_CHECKLOCKTIMEVERIFY, OP_SHA256, OP_TRUE, OP_FALSE
from bitcoin.core.scripteval import VerifyScript, SCRIPT_VERIFY_P2SH
from bitcoin.wallet import CBitcoinAddress, CBitcoinSecret, P2SHBitcoinAddress, P2PKHBitcoinAddress
from xcat.utils import *
import logging
FEE = 0.001*COIN
SelectParams('regtest')
bitcoind = bitcoin.rpc.Proxy()
# Simple CLTV test p2sh
blocknum = bitcoind.getblockcount()
print("Current blocknum on Bitcoin: ", blocknum)
redeemblocknum = blocknum + 1
print("Redeemblocknum on Bitcoin: ", redeemblocknum)
redeemScript = CScript([redeemblocknum, OP_CHECKLOCKTIMEVERIFY])
print("Redeem script for p2sh contract on Bitcoin blockchain: {0}".format(b2x(redeemScript)))
txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey()
# Convert the P2SH scriptPubKey to a base58 Bitcoin address
txin_p2sh_address = CBitcoinAddress.from_scriptPubKey(txin_scriptPubKey)
p2sh = str(txin_p2sh_address)
# Import address at same time you create
bitcoind.importaddress(p2sh, "", False)
bitcoind.generate(3)
blocknum = bitcoind.getblockcount()
print("Current blocknum on Bitcoin 2: ", blocknum)
print("Redeemblocknum on Bitcoin 2: ", redeemblocknum)
send_amount = float(0.01) * COIN
# Import address at same time that you fund it
bitcoind.importaddress(p2sh, "", False)
fund_txid = bitcoind.sendtoaddress(p2sh, send_amount)
txid = b2x(lx(b2x(fund_txid)))
print("fund txid", txid)
# Find the fund tx...
txs = bitcoind.listunspent()
for tx in txs:
if tx['address'] == CBitcoinAddress(p2sh):
print("Found tx to p2sh: {0}".format(p2sh))
fundtx = tx
# redeemScript = CScript(x(redeemScript))
txin = CMutableTxIn(fundtx['outpoint'])
refundAddr = CBitcoinAddress('mvc56qCEVj6p57xZ5URNC3v7qbatudHQ9b')
txout = CMutableTxOut(fundtx['amount'] - FEE, refundAddr.to_scriptPubKey())
# Create the unsigned raw transaction.
tx = CMutableTransaction([txin], [txout])
# tx.nLockTime = 2430
sighash = SignatureHash(redeemScript, tx, 0, SIGHASH_ALL)
# privkey = bitcoind.dumpprivkey(refundPubKey)
# sig = privkey.sign(sighash) + bytes([SIGHASH_ALL])
# Sign without secret
# OP_IF, OP_SHA256, 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
txin.scriptSig = CScript([redeemScript])
# txin.nSequence = 2185
txin_scriptPubKey = redeemScript.to_p2sh_scriptPubKey()
print('Raw redeem transaction hex: {0}'.format(b2x(tx.serialize())))
res = VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,))
print("Script verified, sending raw transaction... ", res)
txid = bitcoind.sendrawtransaction(tx)
refund_tx = b2x(lx(b2x(txid)))

View File

@ -262,10 +262,10 @@ def main():
tradeid = args.arguments[0]
checkBuyStatus(tradeid)
elif command == "step3":
generate(11)
generate(31)
tradeid = args.arguments[0]
checkSellStatus(tradeid)
elif command == "step4":
generate(1)
# generate(1)
tradeid = args.arguments[0]
checkBuyStatus(tradeid)

View File

@ -105,21 +105,39 @@ class zcashProxy():
for tx in txs:
raw = self.zcashd.gettransaction(lx(tx['txid']))['hex']
decoded = self.zcashd.decoderawtransaction(raw)
# print("TXINFO", decoded['vin'][0])
if('txid' in decoded['vin'][0]):
sendid = decoded['vin'][0]['txid']
if (sendid == fundtx_input ):
print("Found funding zcash tx: ", sendid)
res = self.parse_secret(lx(tx['txid']))
secret = res[0]
redeemPubkey = res[1]
if secret is None:
print("Secret not found")
res = self.validateaddress(redeemPubkey)
if res['ismine']:
print("Funding tx already refunded. Sent to your address {0}".format(redeemPubkey))
logging.debug("Redeem transaction with secret not found")
print("Found funding tx: ", sendid)
return self.parse_secret(lx(tx['txid']))
print("Redeem transaction with secret not found")
return
# def find_secret(self, p2sh, fundtx_input):
# print("In find secret zcashrpc")
# txs = self.zcashd.call('listtransactions', "*", 200, 0, True)
# for tx in txs:
# if tx['address'] == p2sh: # Only check txs involving imported p2sh
# raw = self.zcashd.gettransaction(lx(tx['txid']))['hex']
# decoded = self.zcashd.decoderawtransaction(raw)
# print('decoded', decoded)
# if('txid' in decoded['vin'][0]):
# sendid = decoded['vin'][0]['txid']
# print("sendid", sendid)
# if (sendid == fundtx_input ):
# print("Found funding zcash tx: ", sendid)
# res = self.parse_secret(lx(tx['txid']))
# secret = res[0]
# redeemPubkey = res[1]
# if secret is None:
# print("Secret not found")
# res = self.validateaddress(redeemPubkey)
# if res['ismine']:
# print("Funding tx already refunded. Sent to your address {0}".format(redeemPubkey))
# logging.debug("Redeem transaction with secret not found")
# return
def parse_secret(self, txid):
raw = self.zcashd.gettransaction(txid, True)['hex']
decoded = self.zcashd.decoderawtransaction(raw)
@ -130,9 +148,9 @@ class zcashProxy():
secret = x2s(asm[2])
except:
secret = None
redeemPubkey = P2PKHBitcoinAddress.from_pubkey(x(pubkey))
print("redeemPubkey: ", redeemPubkey)
return secret, redeemPubkey
self.redeemPubkey = P2PKHBitcoinAddress.from_pubkey(x(pubkey))
print("redeemPubkey: ", self.redeemPubkey)
return secret
def redeem_contract(self, contract, secret):
# How to find redeemScript and redeemblocknum from blockchain?