示例#1
0
def createNormalCFTransaction(pre_out_ids, pre_cf_hash, spendValue,
                              otherPublicAddrToValueDict, refund_addr):
    tx_ins = __get_tx_ins(pre_out_ids)
    pre_cf = TransactionDao.searchByHash(pre_cf_hash)
    cf_header = pre_cf.cf_header
    cf_header.lack_amount = cf_header.lack_amount - spendValue
    cf_header.pre_hash = pre_cf_hash
    if cf_header.original_hash == '' or cf_header.original_hash == Constants.ZERO_HASH:
        cf_header.original_hash = pre_cf_hash
#     cfscript = b''
    if cf_header.lack_amount <= 0:  #CF suceess
        outValue = cf_header.target_amount
        cfscript = standard_tx_out_script(cf_header.pubkey)


#     elif cf_header.lack_amount == cf_header.target_amount:#CF start
#         outValue = 0
#         cfscript = ScriptPayToAddress(refund_addr).script()
    else:  #CF ing
        outValue = spendValue
        cfscript = standard_tx_out_script(refund_addr)
    #outValue = cf_header.target_amount if cf_header.lack_amount == 0 else spendValue
    cfout = TransactionOut(outValue, cfscript, 0, 0, cf_header.end_time)
    tx_outs = __get_tx_outs(otherPublicAddrToValueDict)
    tx_outs.insert(0, cfout)

    cf = TransactionCF(cf_header, Constants.VERSION, tx_ins, tx_outs,
                       Constants.LOCK_TIME, None, 0)
    if verify(cf):
        insert(cf)
        return cf
示例#2
0
 def electrumx_script_hash(self, bech32: bool = False) -> str:
     addr = self.bech32_p2wpkh_address() if bech32 \
         else self.p2sh_p2wpkh_address()  # type: str
     script = standard_tx_out_script(addr)  # type: bytes
     h = SHA256.new()
     h.update(script)
     return b2h_rev(h.digest())
示例#3
0
文件: tx.py 项目: onestarshang/pycoin
def merge_txs(txs, spendables, payables):

    txs_in = []
    txs_out = []
    unspents = []

    # we use a clever trick here to keep each tx_in corresponding with its tx_out
    for tx in txs:
        smaller = min(len(tx.txs_in), len(tx.txs_out))
        txs_in.extend(tx.txs_in[:smaller])
        txs_out.extend(tx.txs_out[:smaller])
        unspents.extend(tx.unspents[:smaller])
    for tx in txs:
        smaller = min(len(tx.txs_in), len(tx.txs_out))
        txs_in.extend(tx.txs_in[smaller:])
        txs_out.extend(tx.txs_out[smaller:])
        unspents.extend(tx.unspents[smaller:])
    for spendable in spendables:
        txs_in.append(spendable.tx_in())
        unspents.append(spendable)
    for address, coin_value in payables:
        script = standard_tx_out_script(address)
        txs_out.append(TxOut(coin_value, script))

    return txs_in, txs_out, unspents
示例#4
0
    def test_confirm_input(self):
        # create a fake Spendable
        COIN_VALUE = 100000000
        spendables = [
            Spendable(COIN_VALUE, standard_tx_out_script(BITCOIN_ADDRESSES[0]),
                      FAKE_HASHES[1], 0)
        ]

        tx_1 = create_signed_tx(spendables,
                                BITCOIN_ADDRESSES[1:2],
                                wifs=WIFS[:1])

        spendables = tx_1.tx_outs_as_spendable()

        tx_db = dict((tx.hash(), tx) for tx in [tx_1])

        tx_2 = create_signed_tx(spendables,
                                BITCOIN_ADDRESSES[2:3],
                                wifs=WIFS[:3])
        tx_2.validate_unspents(tx_db)

        tx_2 = create_signed_tx([s.as_dict() for s in spendables],
                                BITCOIN_ADDRESSES[2:3],
                                wifs=WIFS[:3])
        tx_2.validate_unspents(tx_db)

        tx_2 = create_signed_tx([s.as_text() for s in spendables],
                                BITCOIN_ADDRESSES[2:3],
                                wifs=WIFS[:3])
        tx_2.validate_unspents(tx_db)
示例#5
0
    def _create_bip69_tx(spendables: List[Spendable],
                         payables: List[Tuple[str, int]],
                         rbf: bool,
                         version: int = 1) -> Tx:
        spendables.sort(key=lambda utxo: (utxo.as_dict()["tx_hash_hex"],
                                          utxo.as_dict()["tx_out_index"]))

        # Create input list from utxos
        # Set sequence numbers to zero if using RBF.
        txs_in = [spendable.tx_in()
                  for spendable in spendables]  # type: List[TxIn]
        if rbf:
            logging.info("Spending with opt-in Replace by Fee! (RBF)")
            for txin in txs_in:
                txin.sequence = 0

        # Create output list from payables
        txs_out = list()  # type: List[TxOut]
        for payable in payables:
            bitcoin_address, coin_value = payable
            script = standard_tx_out_script(bitcoin_address)  # type: bytes
            txs_out.append(TxOut(coin_value, script))
        txs_out.sort(key=lambda txo: (txo.coin_value, b2h(txo.script)))

        tx = Tx(version=version, txs_in=txs_in, txs_out=txs_out)  # type: Tx
        tx.set_unspents(spendables)
        return tx
示例#6
0
def merge_txs(txs, spendables, payables):

    txs_in = []
    txs_out = []
    unspents = []

    # we use a clever trick here to keep each tx_in corresponding with its tx_out
    for tx in txs:
        smaller = min(len(tx.txs_in), len(tx.txs_out))
        txs_in.extend(tx.txs_in[:smaller])
        txs_out.extend(tx.txs_out[:smaller])
        unspents.extend(tx.unspents[:smaller])
    for tx in txs:
        smaller = min(len(tx.txs_in), len(tx.txs_out))
        txs_in.extend(tx.txs_in[smaller:])
        txs_out.extend(tx.txs_out[smaller:])
        unspents.extend(tx.unspents[smaller:])
    for spendable in spendables:
        txs_in.append(spendable.tx_in())
        unspents.append(spendable)
    for address, coin_value in payables:
        script = standard_tx_out_script(address)
        txs_out.append(TxOut(coin_value, script))

    return txs_in, txs_out, unspents
示例#7
0
    def test_simple_spend(self):

        FEE = 10000

        # create a fake Spendable
        COIN_VALUE = 100000000
        spendables = [Spendable(COIN_VALUE, standard_tx_out_script(BITCOIN_ADDRESSES[0]), FAKE_HASHES[1], 0)]

        EXPECTED_IDS = [
            "d28bff6c4a8a0f9e7d5b7df0670d07b43c5613d8c9b14e84707b1e2c0154a978",
            "7afbe63b00171b18f806ebd48190ebc1c68cadf286a85489c06ebe43d146489e",
            "2b90c150ba1d080a0816952f5d9c2642d408989cbc4d4c540591c8c9241294bd",
            "17b0b5b22887081595c1a9ad153e903f63bb8682ae59d6082df018dc617e5e67",
            "dff1b34c243becb096ad2a2d6119973067a8137cc8bf95615e742bbf6f0944c1",
            "206bbfbb759a8f91901d86b62390d7587f6097a32994ece7752d143fc8a02cee",
            "7841412716ad35cbc9954e547ba85be89e5ed0b34ed5fb8d7594517318dc10d6",
            "8b7e643bf47db46ada7a75b8498990b111fe20917b5610ca6759b8b0078ccd5e",
            "5756f0a6d5a2bbb93a07f0729d3773aaafd21393ede3ec0e20b0b5219ca45548",
            "32dcbb34965ea72d2caa59eb1e907aa28bac2afea43214c1809f5d8ed360f30e",
        ]

        for count in range(1, 11):
            tx = create_signed_tx(spendables, BITCOIN_ADDRESSES[1:count+1], wifs=WIFS[:1])
            self.assertEqual(tx.bad_signature_count(), 0)
            self.assertEqual(tx.fee(), FEE)
            self.assertEqual(tx.id(), EXPECTED_IDS[count-1])
            for idx in range(1, count+1):
                self.assertEqual(tx.txs_out[idx-1].bitcoin_address(), BITCOIN_ADDRESSES[idx])
            # TODO: add check that s + s < generator for each signature
            for i in range(count):
                extra = (1 if i < ((COIN_VALUE - FEE) % count) else 0)
                self.assertEqual(tx.txs_out[i].coin_value, (COIN_VALUE - FEE)//count + extra)
示例#8
0
def createFirstCFTransaction(target_amount,
                             pubkey_addr,
                             end_time,
                             pre_out_ids_for_fee=[],
                             cert=''):
    if len(pre_out_ids_for_fee) == 0:
        tx_in = TransactionIn.coinbase_tx_in()
        tx_ins = []
        tx_ins.append(tx_in)
    else:
        tx_ins = __get_tx_ins(pre_out_ids_for_fee)
    cert = SecretKeyDao.searchCertByPubAddr(pubkey_addr)
    cfscript = standard_tx_out_script(pubkey_addr)
    cfout = TransactionOut(0, cfscript, 0, 0, end_time)
    tx_outs = []
    tx_outs.append(cfout)

    original_hash = Constants.ZERO_HASH
    pre_hash = Constants.ZERO_HASH
    lack_amount = target_amount
    cf_header = CFHeader(original_hash, target_amount, pubkey_addr, end_time,
                         pre_hash, lack_amount, cert)
    cf = TransactionCF(cf_header, Constants.VERSION, tx_ins, tx_outs,
                       Constants.LOCK_TIME)
    if verify(cf):
        insert(cf)
        return cf
def coinbase():
    account = Account.Account(TEST_EMAIL1)
    wallet = Wallet.Wallet.from_wallet_key(account.get_wallet_keys()[0])
    address = wallet.address()
    assert is_address_valid(address)
    tx_in = TxIn.coinbase_tx_in(script=b'')
    tx_out = TxOut(50 * 1e8, standard_tx_out_script(address))
    tx = Tx(1, [tx_in], [tx_out])
    return tx.as_hex()
示例#10
0
def __get_tx_outs(publicAddrToValueArray):
    tx_outs = []
    for singlePublicAddrToValueArray in publicAddrToValueArray:
        if len(singlePublicAddrToValueArray) == 2:
            value = singlePublicAddrToValueArray[1]
            script = standard_tx_out_script(singlePublicAddrToValueArray[0])
            tx_out = TransactionOut(value, script, 0, 0)
            tx_outs.append(tx_out)
    return tx_outs
示例#11
0
def tether_tx(tx_ins, private_key, send_amount, receiver):
    """
    simple usdt transaction
    here assume utxo comes from the sender and is used for mine fee
    bitcoin change will be sent back to sender address

    of course different address's utxo can be used for mine fee,
    but should be aware sender is determined by the first input in the tx
    bitcoin change can also be sent back to different address,
    but should be aware receiver is indicated by the last output address that is not the sender

    for full customization, use btc sample p2pkh_tx
    :param tx_ins: utxo from the sender
    :param private_key: private key of the same sender
    :param send_amount: (display amount) * (10 ** 8)
    :param receiver: address to receive usdt
    """
    _txs_in = []
    _un_spent = []
    total_bal = 0

    for tx_id, idx, balance, address in tx_ins:
        total_bal += balance

        # must h2b_rev NOT h2b
        tx_id_b = h2b_rev(tx_id)
        _txs_in.append(TxIn(tx_id_b, idx))

        _un_spent.append(Spendable(balance, standard_tx_out_script(address), tx_id_b, idx))

    txn_fee = estimate_p2pkh_tx_bytes(len(tx_ins), 3) * recommend_satoshi_per_byte()

    _txs_out = [TxOut(total_bal - txn_fee - 546, standard_tx_out_script(tx_ins[0][3])),
                TxOut(0, binascii.unhexlify(omni_tether_script(send_amount))),
                TxOut(546, standard_tx_out_script(receiver))]

    version, lock_time = 1, 0
    tx = Tx(version, _txs_in, _txs_out, lock_time)
    tx.set_unspents(_un_spent)

    solver = build_hash160_lookup([int(private_key, 16)] * len(tx_ins))
    signed_tx = tx.sign(solver, hash_type=SIGHASH_ALL)

    return signed_tx.as_hex(), signed_tx.id()
示例#12
0
def main():
    if len(sys.argv) != 2:
        print("usage: %s address" % sys.argv[0])
        sys.exit(-1)

    # validate the address
    address = sys.argv[1]
    assert is_address_valid(address)

    print("creating coinbase transaction to %s" % address)

    tx_in = TxIn.coinbase_tx_in(script=b'')
    tx_out = TxOut(50*1e8, standard_tx_out_script(address))
    tx = Tx(1, [tx_in], [tx_out])
    print("Here is the tx as hex:\n%s" % tx.as_hex())
示例#13
0
def main():
    if len(sys.argv) != 2:
        print("usage: %s address" % sys.argv[0])
        sys.exit(-1)

    # validate the address
    address = sys.argv[1]
    assert is_address_valid(address)

    print("creating coinbase transaction to %s" % address)

    tx_in = TxIn.coinbase_tx_in(script=b'')
    tx_out = TxOut(50*1e8, standard_tx_out_script(address))
    tx = Tx(1, [tx_in], [tx_out])
    print("Here is the tx as hex:\n%s" % tx.as_hex())
示例#14
0
 def test_p2sh_multisig_sequential_signing(self):
     raw_scripts = [h2b('52210234abcffd2e80ad01c2ec0276ad02682808169c6fafdd25ebfb60703df272b4612102e5baaafff8094e4d77ce8b009d5ebc3de9110085ebd3d96e50cc7ce70faf1752210316ee25e80eb6e6fc734d9c86fa580cbb9c4bfd94a19f0373a22353ececd4db6853ae')]
     txs_in = [TxIn(previous_hash=h2b('43c95d14724437bccc102ccf86aba1ac02415524fd1aefa787db886bba52a10c'), previous_index=0)]
     txs_out = [TxOut(10000, standard_tx_out_script('3KeGeLFmsbmbVdeMLrWp7WYKcA3tdsB4AR'))]
     spendable = {'script_hex': 'a914c4ed4de526461e3efbb79c8b688a6f9282c0464687', 'does_seem_spent': 0,
                  'block_index_spent': 0, 'tx_hash_hex': '0ca152ba6b88db87a7ef1afd24554102aca1ab86cf2c10ccbc374472145dc943',
                  'coin_value': 10000, 'block_index_available': 0, 'tx_out_index': 0}
     tx__prototype = Tx(version=DEFAULT_VERSION, txs_in=txs_in, txs_out=txs_out, unspents=[Spendable.from_dict(spendable)])
     key_1, key_2 = 'Kz6pytJCigYHeMsGLmfHQPJhN5og2wpeSVrU43xWwgHLCAvpsprh', 'Kz7NHgX7MBySA3RSKj9GexUSN6NepEDoPNugSPr5absRDoKgn2dT'
     for ordered_keys in [(key_1, key_2), (key_2, key_1)]:
         tx = copy.deepcopy(tx__prototype)
         for key in ordered_keys:
             self.assertEqual(tx.bad_signature_count(), 1)
             tx.sign(LazySecretExponentDB([key], {}), p2sh_lookup=build_p2sh_lookup(raw_scripts))
         self.assertEqual(tx.bad_signature_count(), 0)
示例#15
0
 def test_sign_pay_to_script_multisig(self):
     M, N = 3, 3
     keys = [Key(secret_exponent=i) for i in range(1, N+2)]
     tx_in = TxIn.coinbase_tx_in(script=b'')
     underlying_script = ScriptMultisig(m=M, sec_keys=[key.sec() for key in keys[:N]]).script()
     address = address_for_pay_to_script(underlying_script)
     self.assertEqual(address, "39qEwuwyb2cAX38MFtrNzvq3KV9hSNov3q")
     script = standard_tx_out_script(address)
     tx_out = TxOut(1000000, script)
     tx1 = Tx(version=1, txs_in=[tx_in], txs_out=[tx_out])
     tx2 = tx_utils.create_tx(tx1.tx_outs_as_spendable(), [address])
     hash160_lookup = build_hash160_lookup(key.secret_exponent() for key in keys[:N])
     p2sh_lookup = build_p2sh_lookup([underlying_script])
     tx2.sign(hash160_lookup=hash160_lookup, p2sh_lookup=p2sh_lookup)
     self.assertEqual(tx2.bad_signature_count(), 0)
示例#16
0
    def test_confirm_input_raises(self):
        FEE = 10000

        # create a fake Spendable
        COIN_VALUE = 100000000
        spendables = [Spendable(COIN_VALUE, standard_tx_out_script(BITCOIN_ADDRESSES[0]), FAKE_HASHES[1], 0)]

        tx_1 = create_signed_tx(spendables, BITCOIN_ADDRESSES[1:2], wifs=WIFS[:1])
        spendables = tx_1.tx_outs_as_spendable()
        spendables[0].coin_value += 100

        tx_db = dict((tx.hash(), tx) for tx in [tx_1])
        tx_2 = create_signed_tx(spendables, BITCOIN_ADDRESSES[2:3], wifs=WIFS[:3])

        self.assertRaises(BadSpendableError, tx_2.validate_unspents, tx_db)
示例#17
0
def standard_tx(coins_from, coins_to):
    txs_in = []
    unspents = []
    for h, idx, tx_out in coins_from:
        txs_in.append(TxIn(h, idx))
        unspents.append(tx_out)

    txs_out = []
    for coin_value, bitcoin_address in coins_to:
        txs_out.append(TxOut(coin_value, standard_tx_out_script(bitcoin_address)))

    version, lock_time = 1, 0
    tx = Tx(version, txs_in, txs_out, lock_time)
    tx.set_unspents(unspents)
    return tx
示例#18
0
def standard_tx(coins_from, coins_to):
    txs_in = []
    unspents = []
    for h, idx, tx_out in coins_from:
        txs_in.append(TxIn(h, idx))
        unspents.append(tx_out)

    txs_out = []
    for coin_value, bitcoin_address in coins_to:
        txs_out.append(
            TxOut(coin_value, standard_tx_out_script(bitcoin_address)))

    version, lock_time = 1, 0
    tx = Tx(version, txs_in, txs_out, lock_time)
    tx.set_unspents(unspents)
    return tx
示例#19
0
    def test_confirm_input_raises(self):
        # create a fake Spendable
        COIN_VALUE = 100000000
        spendables = [
            Spendable(COIN_VALUE, standard_tx_out_script(BITCOIN_ADDRESSES[0]),
                      FAKE_HASHES[1], 0)
        ]

        tx_1 = create_signed_tx(spendables,
                                BITCOIN_ADDRESSES[1:2],
                                wifs=WIFS[:1])
        spendables = tx_1.tx_outs_as_spendable()
        spendables[0].coin_value += 100

        tx_db = dict((tx.hash(), tx) for tx in [tx_1])
        tx_2 = create_signed_tx(spendables,
                                BITCOIN_ADDRESSES[2:3],
                                wifs=WIFS[:3])

        self.assertRaises(BadSpendableError, tx_2.validate_unspents, tx_db)
示例#20
0
    def test_confirm_input(self):
        FEE = 10000

        # create a fake Spendable
        COIN_VALUE = 100000000
        spendables = [Spendable(COIN_VALUE, standard_tx_out_script(BITCOIN_ADDRESSES[0]), FAKE_HASHES[1], 0)]

        tx_1 = create_signed_tx(spendables, BITCOIN_ADDRESSES[1:2], wifs=WIFS[:1])

        spendables = tx_1.tx_outs_as_spendable()

        tx_db = dict((tx.hash(), tx) for tx in [tx_1])

        tx_2 = create_signed_tx(spendables, BITCOIN_ADDRESSES[2:3], wifs=WIFS[:3])
        tx_2.validate_unspents(tx_db)

        tx_2 = create_signed_tx([s.as_dict() for s in spendables], BITCOIN_ADDRESSES[2:3], wifs=WIFS[:3])
        tx_2.validate_unspents(tx_db)

        tx_2 = create_signed_tx([s.as_text() for s in spendables], BITCOIN_ADDRESSES[2:3], wifs=WIFS[:3])
        tx_2.validate_unspents(tx_db)
示例#21
0
    def test_simple_spend(self):

        FEE = 10000

        # create a fake Spendable
        COIN_VALUE = 100000000
        spendables = [
            Spendable(COIN_VALUE, standard_tx_out_script(BITCOIN_ADDRESSES[0]),
                      FAKE_HASHES[1], 0)
        ]

        EXPECTED_IDS = [
            "d28bff6c4a8a0f9e7d5b7df0670d07b43c5613d8c9b14e84707b1e2c0154a978",
            "7afbe63b00171b18f806ebd48190ebc1c68cadf286a85489c06ebe43d146489e",
            "2b90c150ba1d080a0816952f5d9c2642d408989cbc4d4c540591c8c9241294bd",
            "17b0b5b22887081595c1a9ad153e903f63bb8682ae59d6082df018dc617e5e67",
            "dff1b34c243becb096ad2a2d6119973067a8137cc8bf95615e742bbf6f0944c1",
            "206bbfbb759a8f91901d86b62390d7587f6097a32994ece7752d143fc8a02cee",
            "7841412716ad35cbc9954e547ba85be89e5ed0b34ed5fb8d7594517318dc10d6",
            "8b7e643bf47db46ada7a75b8498990b111fe20917b5610ca6759b8b0078ccd5e",
            "5756f0a6d5a2bbb93a07f0729d3773aaafd21393ede3ec0e20b0b5219ca45548",
            "32dcbb34965ea72d2caa59eb1e907aa28bac2afea43214c1809f5d8ed360f30e",
        ]

        for count in range(1, 11):
            tx = create_signed_tx(spendables,
                                  BITCOIN_ADDRESSES[1:count + 1],
                                  wifs=WIFS[:1])
            self.assertEqual(tx.bad_signature_count(), 0)
            self.assertEqual(tx.fee(), FEE)
            self.assertEqual(tx.id(), EXPECTED_IDS[count - 1])
            for idx in range(1, count + 1):
                self.assertEqual(tx.txs_out[idx - 1].bitcoin_address(),
                                 BITCOIN_ADDRESSES[idx])
            # TODO: add check that s + s < generator for each signature
            for i in range(count):
                extra = (1 if i < ((COIN_VALUE - FEE) % count) else 0)
                self.assertEqual(tx.txs_out[i].coin_value,
                                 (COIN_VALUE - FEE) // count + extra)
示例#22
0
    def _create_bip69_tx(spendables: List[Spendable],
                         payables: List[Tuple[str, int]],
                         rbf: bool,
                         version: int = 1) -> Tx:
        """ Create tx inputs and outputs from spendables and payables.
        Sort lexicographically and return unsigned Tx object.

        :param spendables: A list of Spendable objects
        :param payables: A list of payable tuples
        :param rbf: Replace by fee flag
        :param version: Tx format version
        :returns: Fully formed but unsigned Tx object
        """
        spendables.sort(key=lambda utxo: (utxo.as_dict()["tx_hash_hex"],
                                          utxo.as_dict()["tx_out_index"]))

        # Create input list from utxos
        # Set sequence numbers to zero if using RBF.
        txs_in = [spendable.tx_in()
                  for spendable in spendables]  # type: List[TxIn]
        if rbf:
            logging.info("Spending with opt-in Replace by Fee! (RBF)")
            for txin in txs_in:
                txin.sequence = 0

        # Create output list from payables
        txs_out = []  # type: List[TxOut]
        for payable in payables:
            bitcoin_address, coin_value = payable
            script = standard_tx_out_script(bitcoin_address)  # type: bytes
            txs_out.append(TxOut(coin_value, script))
        txs_out.sort(key=lambda txo: (txo.coin_value, b2h(txo.script)))

        tx = Tx(version=version, txs_in=txs_in, txs_out=txs_out)  # type: Tx
        tx.set_unspents(spendables)
        return tx
示例#23
0
    def _test_sighash_single(self, netcode):
        k0 = Key(secret_exponent=PRIV_KEYS[0], is_compressed=True, netcode=netcode)
        k1 = Key(secret_exponent=PRIV_KEYS[1], is_compressed=True, netcode=netcode)
        k2 = Key(secret_exponent=PRIV_KEYS[2], is_compressed=True, netcode=netcode)
        k3 = Key(secret_exponent=PRIV_KEYS[3], is_compressed=True, netcode=netcode)
        k4 = Key(secret_exponent=PRIV_KEYS[4], is_compressed=True, netcode=netcode)
        k5 = Key(secret_exponent=PRIV_KEYS[5], is_compressed=True, netcode=netcode)

        # Fake a coinbase transaction
        coinbase_tx = Tx.coinbase_tx(k0.sec(), 500000000)
        coinbase_tx.txs_out.append(TxOut(1000000000, pycoin_compile('%s OP_CHECKSIG' % b2h(k1.sec()))))
        coinbase_tx.txs_out.append(TxOut(1000000000, pycoin_compile('%s OP_CHECKSIG' % b2h(k2.sec()))))

        self.assertEqual('2acbe1006f7168bad538b477f7844e53de3a31ffddfcfc4c6625276dd714155a',
                b2h_rev(coinbase_tx.hash()))

        # Make the test transaction
        txs_in = [
            TxIn(coinbase_tx.hash(), 0),
            TxIn(coinbase_tx.hash(), 1),
            TxIn(coinbase_tx.hash(), 2),
        ]
        txs_out = [
            TxOut(900000000, standard_tx_out_script(k3.address())),
            TxOut(800000000, standard_tx_out_script(k4.address())),
            TxOut(800000000, standard_tx_out_script(k5.address())),
        ]
        tx = Tx(1, txs_in, txs_out)
        tx.set_unspents(coinbase_tx.txs_out)

        self.assertEqual('791b98ef0a3ac87584fe273bc65abd89821569fd7c83538ac0625a8ca85ba587', b2h_rev(tx.hash()))

        sig_type = SIGHASH_SINGLE

        sig_hash = tx.signature_hash(coinbase_tx.txs_out[0].script, 0, sig_type)
        self.assertEqual('cc52d785a3b4133504d1af9e60cd71ca422609cb41df3a08bbb466b2a98a885e', b2h(to_bytes_32(sig_hash)))

        sig = sigmake(k0, sig_hash, sig_type)
        self.assertTrue(sigcheck(k0, sig_hash, sig[:-1]))

        tx.txs_in[0].script = pycoin_compile(b2h(sig))
        self.assertTrue(tx.is_signature_ok(0))

        sig_hash = tx.signature_hash(coinbase_tx.txs_out[1].script, 1, sig_type)
        self.assertEqual('93bb883d70fccfba9b8aa2028567aca8357937c65af7f6f5ccc6993fd7735fb7', b2h(to_bytes_32(sig_hash)))

        sig = sigmake(k1, sig_hash, sig_type)
        self.assertTrue(sigcheck(k1, sig_hash, sig[:-1]))

        tx.txs_in[1].script = pycoin_compile(b2h(sig))
        self.assertTrue(tx.is_signature_ok(1))

        sig_hash = tx.signature_hash(coinbase_tx.txs_out[2].script, 2, sig_type)
        self.assertEqual('53ef7f67c3541bffcf4e0d06c003c6014e2aa1fb38ff33240b3e1c1f3f8e2a35', b2h(to_bytes_32(sig_hash)))

        sig = sigmake(k2, sig_hash, sig_type)
        self.assertTrue(sigcheck(k2, sig_hash, sig[:-1]))

        tx.txs_in[2].script = pycoin_compile(b2h(sig))
        self.assertTrue(tx.is_signature_ok(2))

        sig_type = SIGHASH_SINGLE | SIGHASH_ANYONECANPAY

        sig_hash = tx.signature_hash(coinbase_tx.txs_out[0].script, 0, sig_type)
        self.assertEqual('2003393d246a7f136692ce7ab819c6eadc54ffea38eb4377ac75d7d461144e75', b2h(to_bytes_32(sig_hash)))

        sig = sigmake(k0, sig_hash, sig_type)
        self.assertTrue(sigcheck(k0, sig_hash, sig[:-1]))

        tx.txs_in[0].script = pycoin_compile(b2h(sig))
        self.assertTrue(tx.is_signature_ok(0))

        sig_hash = tx.signature_hash(coinbase_tx.txs_out[1].script, 1, sig_type)
        self.assertEqual('e3f469ac88e9f35e8eff0bd8ad4ad3bf899c80eb7645947d60860de4a08a35df', b2h(to_bytes_32(sig_hash)))

        sig = sigmake(k1, sig_hash, sig_type)
        self.assertTrue(sigcheck(k1, sig_hash, sig[:-1]))

        tx.txs_in[1].script = pycoin_compile(b2h(sig))
        self.assertTrue(tx.is_signature_ok(1))

        sig_hash = tx.signature_hash(coinbase_tx.txs_out[2].script, 2, sig_type)
        self.assertEqual('bacd7c3ab79cad71807312677c1788ad9565bf3c00ab9a153d206494fb8b7e6a', b2h(to_bytes_32(sig_hash)))

        sig = sigmake(k2, sig_hash, sig_type)
        self.assertTrue(sigcheck(k2, sig_hash, sig[:-1]))

        tx.txs_in[2].script = pycoin_compile(b2h(sig))
        self.assertTrue(tx.is_signature_ok(2))
示例#24
0
    def _test_sighash_single(self, netcode):
        k0 = Key(secret_exponent=PRIV_KEYS[0],
                 is_compressed=True,
                 netcode=netcode)
        k1 = Key(secret_exponent=PRIV_KEYS[1],
                 is_compressed=True,
                 netcode=netcode)
        k2 = Key(secret_exponent=PRIV_KEYS[2],
                 is_compressed=True,
                 netcode=netcode)
        k3 = Key(secret_exponent=PRIV_KEYS[3],
                 is_compressed=True,
                 netcode=netcode)
        k4 = Key(secret_exponent=PRIV_KEYS[4],
                 is_compressed=True,
                 netcode=netcode)
        k5 = Key(secret_exponent=PRIV_KEYS[5],
                 is_compressed=True,
                 netcode=netcode)

        # Fake a coinbase transaction
        coinbase_tx = Tx.coinbase_tx(k0.sec(), 500000000)
        coinbase_tx.txs_out.append(
            TxOut(1000000000,
                  pycoin_compile('%s OP_CHECKSIG' % b2h(k1.sec()))))
        coinbase_tx.txs_out.append(
            TxOut(1000000000,
                  pycoin_compile('%s OP_CHECKSIG' % b2h(k2.sec()))))

        self.assertEqual(
            '2acbe1006f7168bad538b477f7844e53de3a31ffddfcfc4c6625276dd714155a',
            b2h_rev(coinbase_tx.hash()))

        # Make the test transaction
        txs_in = [
            TxIn(coinbase_tx.hash(), 0),
            TxIn(coinbase_tx.hash(), 1),
            TxIn(coinbase_tx.hash(), 2),
        ]
        txs_out = [
            TxOut(900000000, standard_tx_out_script(k3.address())),
            TxOut(800000000, standard_tx_out_script(k4.address())),
            TxOut(800000000, standard_tx_out_script(k5.address())),
        ]
        tx = Tx(1, txs_in, txs_out)
        tx.set_unspents(coinbase_tx.txs_out)

        self.assertEqual(
            '791b98ef0a3ac87584fe273bc65abd89821569fd7c83538ac0625a8ca85ba587',
            b2h_rev(tx.hash()))

        sig_type = SIGHASH_SINGLE

        sig_hash = tx.signature_hash(coinbase_tx.txs_out[0].script, 0,
                                     sig_type)
        self.assertEqual(
            'cc52d785a3b4133504d1af9e60cd71ca422609cb41df3a08bbb466b2a98a885e',
            b2h(to_bytes_32(sig_hash)))

        sig = sigmake(k0, sig_hash, sig_type)
        self.assertTrue(sigcheck(k0, sig_hash, sig[:-1]))

        tx.txs_in[0].script = pycoin_compile(b2h(sig))
        self.assertTrue(tx.is_signature_ok(0))

        sig_hash = tx.signature_hash(coinbase_tx.txs_out[1].script, 1,
                                     sig_type)
        self.assertEqual(
            '93bb883d70fccfba9b8aa2028567aca8357937c65af7f6f5ccc6993fd7735fb7',
            b2h(to_bytes_32(sig_hash)))

        sig = sigmake(k1, sig_hash, sig_type)
        self.assertTrue(sigcheck(k1, sig_hash, sig[:-1]))

        tx.txs_in[1].script = pycoin_compile(b2h(sig))
        self.assertTrue(tx.is_signature_ok(1))

        sig_hash = tx.signature_hash(coinbase_tx.txs_out[2].script, 2,
                                     sig_type)
        self.assertEqual(
            '53ef7f67c3541bffcf4e0d06c003c6014e2aa1fb38ff33240b3e1c1f3f8e2a35',
            b2h(to_bytes_32(sig_hash)))

        sig = sigmake(k2, sig_hash, sig_type)
        self.assertTrue(sigcheck(k2, sig_hash, sig[:-1]))

        tx.txs_in[2].script = pycoin_compile(b2h(sig))
        self.assertTrue(tx.is_signature_ok(2))

        sig_type = SIGHASH_SINGLE | SIGHASH_ANYONECANPAY

        sig_hash = tx.signature_hash(coinbase_tx.txs_out[0].script, 0,
                                     sig_type)
        self.assertEqual(
            '2003393d246a7f136692ce7ab819c6eadc54ffea38eb4377ac75d7d461144e75',
            b2h(to_bytes_32(sig_hash)))

        sig = sigmake(k0, sig_hash, sig_type)
        self.assertTrue(sigcheck(k0, sig_hash, sig[:-1]))

        tx.txs_in[0].script = pycoin_compile(b2h(sig))
        self.assertTrue(tx.is_signature_ok(0))

        sig_hash = tx.signature_hash(coinbase_tx.txs_out[1].script, 1,
                                     sig_type)
        self.assertEqual(
            'e3f469ac88e9f35e8eff0bd8ad4ad3bf899c80eb7645947d60860de4a08a35df',
            b2h(to_bytes_32(sig_hash)))

        sig = sigmake(k1, sig_hash, sig_type)
        self.assertTrue(sigcheck(k1, sig_hash, sig[:-1]))

        tx.txs_in[1].script = pycoin_compile(b2h(sig))
        self.assertTrue(tx.is_signature_ok(1))

        sig_hash = tx.signature_hash(coinbase_tx.txs_out[2].script, 2,
                                     sig_type)
        self.assertEqual(
            'bacd7c3ab79cad71807312677c1788ad9565bf3c00ab9a153d206494fb8b7e6a',
            b2h(to_bytes_32(sig_hash)))

        sig = sigmake(k2, sig_hash, sig_type)
        self.assertTrue(sigcheck(k2, sig_hash, sig[:-1]))

        tx.txs_in[2].script = pycoin_compile(b2h(sig))
        self.assertTrue(tx.is_signature_ok(2))
示例#25
0
文件: tx.py 项目: Stevengu999/pycoin
def main():
    parser = create_parser()
    args = parser.parse_args()

    (txs, spendables, payables, key_iters, p2sh_lookup, tx_db,
     warning_tx_cache, warning_tx_for_tx_hash, warning_spendables) = parse_context(args, parser)

    txs_in = []
    txs_out = []
    unspents = []

    # we use a clever trick here to keep each tx_in corresponding with its tx_out
    for tx in txs:
        smaller = min(len(tx.txs_in), len(tx.txs_out))
        txs_in.extend(tx.txs_in[:smaller])
        txs_out.extend(tx.txs_out[:smaller])
        unspents.extend(tx.unspents[:smaller])
    for tx in txs:
        smaller = min(len(tx.txs_in), len(tx.txs_out))
        txs_in.extend(tx.txs_in[smaller:])
        txs_out.extend(tx.txs_out[smaller:])
        unspents.extend(tx.unspents[smaller:])
    for spendable in spendables:
        txs_in.append(spendable.tx_in())
        unspents.append(spendable)
    for address, coin_value in payables:
        script = standard_tx_out_script(address)
        txs_out.append(TxOut(coin_value, script))

    lock_time = args.lock_time
    version = args.transaction_version

    # if no lock_time is explicitly set, inherit from the first tx or use default
    if lock_time is None:
        if txs:
            lock_time = txs[0].lock_time
        else:
            lock_time = DEFAULT_LOCK_TIME

    # if no version is explicitly set, inherit from the first tx or use default
    if version is None:
        if txs:
            version = txs[0].version
        else:
            version = DEFAULT_VERSION

    if args.remove_tx_in:
        s = set(args.remove_tx_in)
        txs_in = [tx_in for idx, tx_in in enumerate(txs_in) if idx not in s]

    if args.remove_tx_out:
        s = set(args.remove_tx_out)
        txs_out = [tx_out for idx, tx_out in enumerate(txs_out) if idx not in s]

    tx = Tx(txs_in=txs_in, txs_out=txs_out, lock_time=lock_time, version=version, unspents=unspents)

    fee = args.fee
    try:
        distribute_from_split_pool(tx, fee)
    except ValueError as ex:
        print("warning: %s" % ex.args[0], file=sys.stderr)

    unsigned_before = tx.bad_signature_count()
    unsigned_after = unsigned_before
    if unsigned_before > 0 and key_iters:
        def wif_iter(iters):
            while len(iters) > 0:
                for idx, iter in enumerate(iters):
                    try:
                        wif = next(iter)
                        yield wif
                    except StopIteration:
                        iters = iters[:idx] + iters[idx+1:]
                        break

        print("signing...", file=sys.stderr)
        sign_tx(tx, wif_iter(key_iters), p2sh_lookup=p2sh_lookup)

        unsigned_after = tx.bad_signature_count()
        if unsigned_after > 0:
            print("warning: %d TxIn items still unsigned" % unsigned_after, file=sys.stderr)

    if len(tx.txs_in) == 0:
        print("warning: transaction has no inputs", file=sys.stderr)

    if len(tx.txs_out) == 0:
        print("warning: transaction has no outputs", file=sys.stderr)

    include_unspents = (unsigned_after > 0)
    tx_as_hex = tx.as_hex(include_unspents=include_unspents)

    if args.output_file:
        f = args.output_file
        if f.name.endswith(".hex"):
            f.write(tx_as_hex.encode("utf8"))
        else:
            tx.stream(f)
            if include_unspents:
                tx.stream_unspents(f)
        f.close()
    elif args.show_unspents:
        for spendable in tx.tx_outs_as_spendable():
            print(spendable.as_text())
    else:
        if not tx.missing_unspents():
            check_fees(tx)
        dump_tx(tx, args.network, args.verbose_signature, args.disassemble, args.trace, args.pdb)
        if include_unspents:
            print("including unspents in hex dump since transaction not fully signed")
        print(tx_as_hex)

    if args.cache:
        if tx_db is None:
            warning_tx_cache = message_about_tx_cache_env()
            warning_tx_for_tx_hash = message_about_tx_for_tx_hash_env(args.network)
            tx_db = get_tx_db(args.network)
        tx_db.put(tx)

    if args.bitcoind_url:
        if tx_db is None:
            warning_tx_cache = message_about_tx_cache_env()
            warning_tx_for_tx_hash = message_about_tx_for_tx_hash_env(args.network)
            tx_db = get_tx_db(args.network)
        validate_bitcoind(tx, tx_db, args.bitcoind_url)

    if tx.missing_unspents():
        print("\n** can't validate transaction as source transactions missing", file=sys.stderr)
    else:
        try:
            if tx_db is None:
                warning_tx_cache = message_about_tx_cache_env()
                warning_tx_for_tx_hash = message_about_tx_for_tx_hash_env(args.network)
                tx_db = get_tx_db(args.network)
            tx.validate_unspents(tx_db)
            print('all incoming transaction values validated')
        except BadSpendableError as ex:
            print("\n**** ERROR: FEES INCORRECTLY STATED: %s" % ex.args[0], file=sys.stderr)
        except Exception as ex:
            print("\n*** can't validate source transactions as untampered: %s" %
                  ex.args[0], file=sys.stderr)

    # print warnings
    for m in [warning_tx_cache, warning_tx_for_tx_hash, warning_spendables]:
        if m:
            print("warning: %s" % m, file=sys.stderr)
示例#26
0
    async def build_tx(self,
                       priv: str,
                       addrs: List[Tuple[str, D]],
                       split_fee=True):
        """
        We distribute fee equally on every recipient by reducing the amount
        of money they will receive. The rest will go back to the sender
        as a change.

        :param priv: WIF private key of sender -> str
        :param addrs: distribution -> [(addr1, amount1), (addr2, amount2),...]
        :return: transaction id -> str
        """
        addr = Key.from_text(priv).address()

        spendables = await self.get_spendable_list_for_addr(addr)
        addrs.append((addr, D(0)))

        txs_out = []
        for payable in addrs:
            bitcoin_address, coin_value = payable
            coin_value *= COIN
            script = standard_tx_out_script(bitcoin_address)
            txs_out.append(TxOut(coin_value, script))

        txs_in = [spendable.tx_in() for spendable in spendables]
        tx = Tx(version=1, txs_in=txs_in, txs_out=txs_out, lock_time=0)

        tx.set_unspents(spendables)

        fee = await self.calc_fee(tx)

        total_coin_value = sum(spendable.coin_value
                               for spendable in tx.unspents)
        coins_allocated = sum(tx_out.coin_value for tx_out in tx.txs_out)

        if split_fee:
            fee_per_tx_out, extra_count = divmod(fee, len(tx.txs_out) - 1)

            if coins_allocated > total_coin_value:
                raise NotEnoughAmountError(
                    'Coins allocated exceeds total spendable: '
                    f'allocated: {coins_allocated}, '
                    f'spendable: {total_coin_value}')

            for tx_out in tx.txs_out:
                if tx_out.address(netcode=self.NETCODE) == addr:
                    tx_out.coin_value = total_coin_value - coins_allocated
                else:
                    tx_out.coin_value -= fee_per_tx_out
                    if extra_count > 0:
                        tx_out.coin_value -= 1
                        extra_count -= 1
                    if tx_out.coin_value < 1:
                        raise NotEnoughAmountError(
                            'Not enough in each output to spread fee evenly: '
                            f'{tx_out.address} allocated too little')
        else:
            if (coins_allocated + fee) > total_coin_value:
                raise NotEnoughAmountError(
                    'Coins allocated exceeds total spendable: '
                    f'allocated: {coins_allocated}, '
                    f'fee: {fee}, '
                    f'spendable: {total_coin_value}')
            for tx_out in tx.txs_out:
                if tx_out.address(netcode=self.NETCODE) == addr:
                    tx_out.coin_value = (total_coin_value - coins_allocated -
                                         fee)
                    break
        return tx
示例#27
0
def main():
    parser = create_parser()
    args = parser.parse_args()

    (txs, spendables, payables, key_iters, p2sh_lookup, tx_db,
     warning_tx_cache, warning_tx_for_tx_hash,
     warning_spendables) = parse_context(args, parser)

    txs_in = []
    txs_out = []
    unspents = []

    # we use a clever trick here to keep each tx_in corresponding with its tx_out
    for tx in txs:
        smaller = min(len(tx.txs_in), len(tx.txs_out))
        txs_in.extend(tx.txs_in[:smaller])
        txs_out.extend(tx.txs_out[:smaller])
        unspents.extend(tx.unspents[:smaller])
    for tx in txs:
        smaller = min(len(tx.txs_in), len(tx.txs_out))
        txs_in.extend(tx.txs_in[smaller:])
        txs_out.extend(tx.txs_out[smaller:])
        unspents.extend(tx.unspents[smaller:])
    for spendable in spendables:
        txs_in.append(spendable.tx_in())
        unspents.append(spendable)
    for address, coin_value in payables:
        script = standard_tx_out_script(address)
        txs_out.append(TxOut(coin_value, script))

    lock_time = args.lock_time
    version = args.transaction_version

    # if no lock_time is explicitly set, inherit from the first tx or use default
    if lock_time is None:
        if txs:
            lock_time = txs[0].lock_time
        else:
            lock_time = DEFAULT_LOCK_TIME

    # if no version is explicitly set, inherit from the first tx or use default
    if version is None:
        if txs:
            version = txs[0].version
        else:
            version = DEFAULT_VERSION

    if args.remove_tx_in:
        s = set(args.remove_tx_in)
        txs_in = [tx_in for idx, tx_in in enumerate(txs_in) if idx not in s]

    if args.remove_tx_out:
        s = set(args.remove_tx_out)
        txs_out = [
            tx_out for idx, tx_out in enumerate(txs_out) if idx not in s
        ]

    tx = Tx(txs_in=txs_in,
            txs_out=txs_out,
            lock_time=lock_time,
            version=version,
            unspents=unspents)

    fee = args.fee
    try:
        distribute_from_split_pool(tx, fee)
    except ValueError as ex:
        print("warning: %s" % ex.args[0], file=sys.stderr)

    unsigned_before = tx.bad_signature_count()
    unsigned_after = unsigned_before
    if unsigned_before > 0 and key_iters:

        def wif_iter(iters):
            while len(iters) > 0:
                for idx, iter in enumerate(iters):
                    try:
                        wif = next(iter)
                        yield wif
                    except StopIteration:
                        iters = iters[:idx] + iters[idx + 1:]
                        break

        print("signing...", file=sys.stderr)
        sign_tx(tx, wif_iter(key_iters), p2sh_lookup=p2sh_lookup)

        unsigned_after = tx.bad_signature_count()
        if unsigned_after > 0:
            print("warning: %d TxIn items still unsigned" % unsigned_after,
                  file=sys.stderr)

    if len(tx.txs_in) == 0:
        print("warning: transaction has no inputs", file=sys.stderr)

    if len(tx.txs_out) == 0:
        print("warning: transaction has no outputs", file=sys.stderr)

    include_unspents = (unsigned_after > 0)
    tx_as_hex = tx.as_hex(include_unspents=include_unspents)

    if args.output_file:
        f = args.output_file
        if f.name.endswith(".hex"):
            f.write(tx_as_hex.encode("utf8"))
        else:
            tx.stream(f)
            if include_unspents:
                tx.stream_unspents(f)
        f.close()
    elif args.show_unspents:
        for spendable in tx.tx_outs_as_spendable():
            print(spendable.as_text())
    else:
        if not tx.missing_unspents():
            check_fees(tx)
        dump_tx(tx, args.network, args.verbose_signature, args.disassemble,
                args.trace, args.pdb)
        if include_unspents:
            print(
                "including unspents in hex dump since transaction not fully signed"
            )
        print(tx_as_hex)

    if args.cache:
        if tx_db is None:
            warning_tx_cache = message_about_tx_cache_env()
            warning_tx_for_tx_hash = message_about_tx_for_tx_hash_env(
                args.network)
            tx_db = get_tx_db(args.network)
        tx_db.put(tx)

    if args.bitcoind_url:
        if tx_db is None:
            warning_tx_cache = message_about_tx_cache_env()
            warning_tx_for_tx_hash = message_about_tx_for_tx_hash_env(
                args.network)
            tx_db = get_tx_db(args.network)
        validate_bitcoind(tx, tx_db, args.bitcoind_url)

    if tx.missing_unspents():
        print("\n** can't validate transaction as source transactions missing",
              file=sys.stderr)
    else:
        try:
            if tx_db is None:
                warning_tx_cache = message_about_tx_cache_env()
                warning_tx_for_tx_hash = message_about_tx_for_tx_hash_env(
                    args.network)
                tx_db = get_tx_db(args.network)
            tx.validate_unspents(tx_db)
            print('all incoming transaction values validated')
        except BadSpendableError as ex:
            print("\n**** ERROR: FEES INCORRECTLY STATED: %s" % ex.args[0],
                  file=sys.stderr)
        except Exception as ex:
            print(
                "\n*** can't validate source transactions as untampered: %s" %
                ex.args[0],
                file=sys.stderr)

    # print warnings
    for m in [warning_tx_cache, warning_tx_for_tx_hash, warning_spendables]:
        if m:
            print("warning: %s" % m, file=sys.stderr)