Esempio n. 1
0
    def __init__(self,
                 network,
                 contract: str,
                 raw_transaction: Optional[str] = None,
                 transaction_address: Optional[str] = None):

        if not raw_transaction and not transaction_address:
            raise ValueError(
                'Provide raw_transaction or transaction_address argument.')

        self.network = network
        self.symbol = self.network.default_symbol
        self.contract = contract
        self.tx = None
        self.vout = None
        self.confirmations = None
        self.tx_address = transaction_address
        if raw_transaction:
            self.tx = self.network.deserialize_raw_transaction(raw_transaction)
            try:
                self.vout = self.tx.vout[0]
            except IndexError:
                raise ValueError('Given transaction has no outputs.')
        else:
            tx_json = self.network.get_transaction(transaction_address)
            if not tx_json:
                raise ValueError('No transaction found under given address.')

            self.vout = self.network.get_first_vout_from_tx_json(tx_json)
            self.confirmations = self.network.get_confirmations_from_tx_json(
                tx_json)

        if not self.vout:
            raise ValueError('Given transaction has no outputs.')

        contract_tx_out = self.vout
        contract_script = script.CScript.fromhex(self.contract)
        script_pub_key = contract_script.to_p2sh_scriptPubKey()
        valid_p2sh = script_pub_key == contract_tx_out.scriptPubKey
        self.address = str(CBitcoinAddress.from_scriptPubKey(script_pub_key))
        try:
            self.balance = self.network.get_balance(self.address)
        except NotImplementedError:
            self.balance = None

        script_ops = list(contract_script)
        if valid_p2sh and self.is_valid_contract_script(script_ops):
            self.recipient_address = str(
                P2PKHBitcoinAddress.from_bytes(script_ops[6]))
            self.refund_address = str(
                P2PKHBitcoinAddress.from_bytes(script_ops[13]))
            self.locktime_timestamp = int.from_bytes(script_ops[8],
                                                     byteorder='little')
            self.locktime = datetime.utcfromtimestamp(self.locktime_timestamp)
            self.secret_hash = b2x(script_ops[2])
            self.value = from_base_units(contract_tx_out.nValue)
        else:
            raise ValueError('Given transaction is not a valid contract.')
Esempio n. 2
0
    def redeem_contract(self, contract, secret):
        print("Parsing script for redeem_contract...")
        scriptarray = self.parse_script(contract.redeemScript)
        redeemblocknum = scriptarray[8]
        redeemPubKey = P2PKHBitcoinAddress.from_bytes(x(scriptarray[6]))
        refundPubKey = P2PKHBitcoinAddress.from_bytes(x(scriptarray[13]))
        p2sh = contract.p2sh
        #checking there are funds in the address
        amount = self.check_funds(p2sh)
        if(amount == 0):
            print("address ", p2sh, " not funded")
            quit()
        fundtx = self.find_transaction_to_address(p2sh)
        amount = fundtx['amount'] / COIN
        # print("Found fund_tx: ", fundtx)
        p2sh = P2SHBitcoinAddress(p2sh)
        if fundtx['address'] == p2sh:
            print("Found {0} in p2sh {1}, redeeming...".format(amount, p2sh))

            blockcount = self.bitcoind.getblockcount()
            print("\nCurrent blocknum at time of redeem on Zcash:", blockcount)
            if blockcount < int(redeemblocknum):
                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: protect privkey better, separate signing from rawtx creation
                privkey = self.bitcoind.dumpprivkey(redeemPubKey)
                sig = privkey.sign(sighash) + bytes([SIGHASH_ALL])
                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('Raw redeem transaction hex: ', b2x(tx.serialize()))
                VerifyScript(txin.scriptSig, txin_scriptPubKey, tx, 0, (SCRIPT_VERIFY_P2SH,))
                print("Script verified, sending raw transaction...")
                txid = self.bitcoind.sendrawtransaction(tx)
                fund_tx = str(fundtx['outpoint'])
                redeem_tx =  b2x(lx(b2x(txid)))
                return  {"redeem_tx": redeem_tx, "fund_tx": fund_tx}
            else:
                print("nLocktime exceeded, refunding")
                print('refundPubKey', refundPubKey)
                txid = self.bitcoind.sendtoaddress(refundPubKey, fundtx['amount'] - FEE)
                fund_tx = str(fundtx['outpoint'])
                refund_tx =  b2x(lx(b2x(txid)))
                return  {"refund_tx": refund_tx, "fund_tx": fund_tx}
        else:
            print("No contract for this p2sh found in database", p2sh)
Esempio n. 3
0
    def redeem_contract(self, contract, secret):
        print("Parsing script for redeem_contract...")
        scriptarray = self.parse_script(contract.redeemScript)
        redeemblocknum = scriptarray[8]
        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
        amount = self.check_funds(p2sh)
        if(amount == 0):
            print("address ", p2sh, " not funded")
            quit()
        fundtx = self.find_transaction_to_address(p2sh)
        amount = fundtx['amount'] / COIN
        # print("Found fund_tx: ", fundtx)
        p2sh = P2SHBitcoinAddress(p2sh)
        if fundtx['address'] == p2sh:
            print("Found {0} in p2sh {1}, redeeming...".format(amount, p2sh))

            blockcount = self.bitcoind.getblockcount()
            print("\nCurrent blocknum at time of redeem on Bitcoin:", blockcount)
            if blockcount < int(redeemblocknum):
                return self.redeem(contract, fundtx, secret)
            else:
                print("nLocktime exceeded, refunding")
                return self.refund(contract)
        else:
            print("No contract for this p2sh found in database", p2sh)
Esempio n. 4
0
 def test_json_roundtrip(self):
     VALUES = [
         42,
         0,
         -42,
         2100000000000000,
         -2100000000000000,
         "basic string",
         "\u1111Unicode",
         "\U00010000Wide Unicode",
         "\x00\n\t\r\nEscape codes",
         "\"'\"Quotes",
         "",
         None,
         b"\x00\x01\xFFBinary data",
         b"",
         CBase58Data.from_bytes(b'\x00\x01\xFF', 42),
         P2SHBitcoinAddress.from_bytes(b'\x00\x01\xFF'),
         P2PKHBitcoinAddress.from_bytes(b'\x00\x01\xFF'),
         CMutableTxIn(COutPoint(b'\x00' * 16 + b'\xFF' * 16, 42),
                      CScript(b'\x00\x01\xFF'), 42),
         CMutableTxOut(42, CScript(b'\x00\x01\xFF')),
         CMutableTransaction([
             CMutableTxIn(COutPoint(b'\x00' * 32, 42),
                          CScript(b'\x00\x01\xFF'), 42),
             CMutableTxIn(COutPoint(b'\xFF' * 32, 42),
                          CScript(b'\xFF\x01\x00'), 43)
         ], [
             CMutableTxOut(42, CScript(b'\x00\x01\xFF')),
             CMutableTxOut(43, CScript(b'\xFF\x01\x00'))
         ], 42, 3),
         [
             1,
             b'\x00\x01\xFF',
             "List Test",
         ],
         {
             'a': 1,
             'key': b'\xFF\x01\x00',
             1: 'Dictionary Test'
         },
         [
             {
                 3: [
                     0,
                     1,
                     2,
                 ],
             },
             [
                 [
                     b'\xFFRecursion Test',
                 ],
             ],
         ],
     ]
     for value in VALUES:
         self.assertEqual(from_json(to_json(value)), value)
Esempio n. 5
0
 def test_json_roundtrip(self):
     VALUES = [
         42,
         0,
         -42,
         2100000000000000,
         -2100000000000000,
         "basic string",
         "\u1111Unicode",
         "\U00010000Wide Unicode",
         "\x00\n\t\r\nEscape codes",
         '"\'"Quotes',
         "",
         None,
         b"\x00\x01\xFFBinary data",
         b"",
         CBase58Data.from_bytes(b"\x00\x01\xFF", 42),
         P2SHBitcoinAddress.from_bytes(b"\x00\x01\xFF"),
         P2PKHBitcoinAddress.from_bytes(b"\x00\x01\xFF"),
         CMutableTxIn(COutPoint(b"\x00" * 16 + b"\xFF" * 16, 42), CScript(b"\x00\x01\xFF"), 42),
         CMutableTxOut(42, CScript(b"\x00\x01\xFF")),
         CMutableTransaction(
             [
                 CMutableTxIn(COutPoint(b"\x00" * 32, 42), CScript(b"\x00\x01\xFF"), 42),
                 CMutableTxIn(COutPoint(b"\xFF" * 32, 42), CScript(b"\xFF\x01\x00"), 43),
             ],
             [CMutableTxOut(42, CScript(b"\x00\x01\xFF")), CMutableTxOut(43, CScript(b"\xFF\x01\x00"))],
             42,
             3,
         ),
         [1, b"\x00\x01\xFF", "List Test"],
         {"a": 1, "key": b"\xFF\x01\x00", 1: "Dictionary Test"},
         [{3: [0, 1, 2]}, [[b"\xFFRecursion Test"]]],
     ]
     for value in VALUES:
         self.assertEqual(from_json(to_json(value)), value)
Esempio n. 6
0
    def __init__(
        self,
        network,
        contract: str,
        raw_transaction: Optional[str]=None,
        transaction_address: Optional[str]=None
    ):

        if not raw_transaction and not transaction_address:
            raise ValueError('Provide raw_transaction or transaction_address argument.')

        self.network = network
        self.symbol = self.network.default_symbol
        self.contract = contract
        self.tx = None
        self.vout = None
        self.confirmations = None
        self.tx_address = transaction_address
        if raw_transaction:
            self.tx = self.network.deserialize_raw_transaction(raw_transaction)
            try:
                self.vout = self.tx.vout[0]
            except IndexError:
                raise ValueError('Given transaction has no outputs.')
        else:
            tx_json = get_transaction(network.default_symbol, transaction_address, network.is_test_network())
            if not tx_json:
                raise ValueError('No transaction found under given address.')
            if 'hex' in tx_json:
                # transaction from blockcypher or raven explorer
                self.tx = self.network.deserialize_raw_transaction(tx_json['hex'])
                self.vout = self.tx.vout[0]
            else:
                # transaction from cryptoid
                incorrect_cscript = script.CScript.fromhex(tx_json['outputs'][0]['script'])
                correct_cscript = script.CScript([script.OP_HASH160, list(incorrect_cscript)[2], script.OP_EQUAL])
                nValue = to_base_units(tx_json['outputs'][0]['amount'])
                self.vout = CTxOut(nValue, correct_cscript)

            if 'confirmations' in tx_json:
                self.confirmations = tx_json['confirmations']
            elif 'block_height' in tx_json:
                self.confirmations = self.network.latest_block - tx_json['block_height']
            elif 'block' in tx_json:
                self.confirmations = self.network.latest_block - tx_json['block']

        if not self.vout:
            raise ValueError('Given transaction has no outputs.')

        contract_tx_out = self.vout
        contract_script = script.CScript.fromhex(self.contract)
        script_pub_key = contract_script.to_p2sh_scriptPubKey()
        valid_p2sh = script_pub_key == contract_tx_out.scriptPubKey
        self.address = str(CBitcoinAddress.from_scriptPubKey(script_pub_key))
        self.balance = get_balance(self.network, self.address)

        script_ops = list(contract_script)
        if valid_p2sh and self.is_valid_contract_script(script_ops):
            self.recipient_address = str(P2PKHBitcoinAddress.from_bytes(script_ops[6]))
            self.refund_address = str(P2PKHBitcoinAddress.from_bytes(script_ops[13]))
            self.locktime_timestamp = int.from_bytes(script_ops[8], byteorder='little')
            self.locktime = datetime.utcfromtimestamp(self.locktime_timestamp)
            self.secret_hash = b2x(script_ops[2])
            self.value = from_base_units(contract_tx_out.nValue)
        else:
            raise ValueError('Given transaction is not a valid contract.')
Esempio n. 7
0
 def find_refundAddr(self, contract):
     scriptarray = parse_script(contract.redeemScript)
     funder = scriptarray[13]
     refundAddr = P2PKHBitcoinAddress.from_bytes(x(funder))
     return refundAddr
Esempio n. 8
0
import hashlib
from bitcoin.core import b2x, lx, COIN, CMutableTxOut, CMutableTxIn, CMutableTransaction, CBlock
from bitcoin.wallet import P2PKHBitcoinAddress

receiver_pkh = bytes.fromhex('346753e81b93e3f1567a16f3009c7c65c768d865')
print('receiver_pkh: "%s"' % receiver_pkh.hex())
receiver = P2PKHBitcoinAddress.from_bytes(receiver_pkh)
tx = CMutableTransaction()

tx.vin.append(CMutableTxIn())
tx.vout.append(CMutableTxOut(10, receiver.to_scriptPubKey()))
print('tx: "%s"' % tx.serialize().hex())

print('txid: "%s"' % tx.GetTxid().hex())

blk = CBlock(vtx=[tx])
blk_mtr = blk.calc_merkle_root()
print('block_mtr: "%s"' % blk_mtr.hex())

mmr = hashlib.sha256(b'\x00' + blk_mtr).digest()
print('mmr: "%s"' % mmr.hex())
Esempio n. 9
0
def find_redeemAddr(contract):
    scriptarray = parse_script(contract.redeemScript)
    redeemer = scriptarray[6]
    redeemAddr = P2PKHBitcoinAddress.from_bytes(x(redeemer))
    return redeemAddr