Ejemplo n.º 1
0
    def test_immutable_tx_creation_with_mutable_parts_specified(self):
        tx = CTransaction(
            vin=[CMutableTxIn(prevout=COutPoint(hash=b'a' * 32, n=0))],
            vout=[CMutableTxOut(nValue=1)],
            witness=CMutableTxWitness(
                [CMutableTxInWitness(CScriptWitness([CScript([0])]))]))

        def check_immutable_parts(tx):
            self.assertTrue(tx.vin[0].is_immutable())
            self.assertTrue(tx.vin[0].is_immutable())
            self.assertTrue(tx.vout[0].is_immutable())
            self.assertTrue(tx.wit.is_immutable())
            self.assertTrue(tx.wit.vtxinwit[0].is_immutable())

        check_immutable_parts(tx)

        # Test that if we deserialize with CTransaction,
        # all the parts are immutable
        tx = CTransaction.deserialize(tx.serialize())
        check_immutable_parts(tx)

        # Test some parts separately, because when created via
        # CMutableTransaction instantiation, they are created with from_*
        # methods, and not directly

        txin = CTxIn(prevout=CMutableOutPoint(hash=b'a' * 32, n=0))
        self.assertTrue(txin.prevout.is_immutable())

        wit = CTxWitness((CMutableTxInWitness(), ))
        self.assertTrue(wit.vtxinwit[0].is_immutable())
Ejemplo n.º 2
0
    def test_blind_unnblind_sign(self):
        if not secp256k1_has_zkp:
            warn_zkp_unavailable()
            return

        with open(
                os.path.dirname(__file__) + '/data/elements_txs_blinding.json',
                'r') as fd:
            for bundle in json.load(fd):
                blinded_tx_raw = x(bundle['blinded']['hex'])
                blinded_tx = CTransaction.deserialize(blinded_tx_raw)
                self.assertEqual(blinded_tx.serialize(), blinded_tx_raw)
                self.check_serialize_deserialize(blinded_tx, blinded_tx_raw,
                                                 bundle['blinded'])
                unblinded_tx_raw = x(bundle['unblinded']['hex'])
                unblinded_tx = CTransaction.deserialize(unblinded_tx_raw)

                self.assertEqual(unblinded_tx.serialize(), unblinded_tx_raw)
                self.check_serialize_deserialize(unblinded_tx,
                                                 unblinded_tx_raw,
                                                 bundle['unblinded'])
                signed_tx_raw = x(bundle['signed_hex'])
                signed_tx = CTransaction.deserialize(signed_tx_raw)
                self.assertEqual(signed_tx.serialize(), signed_tx_raw)
                blinding_derivation_key = CKey(
                    lx(bundle['blinding_derivation_key']))

                # ensure that str and repr works
                for f in (str, repr):
                    f(unblinded_tx)
                    f(blinded_tx)
                    f(signed_tx)

                if len(blinded_tx.vout) != len(unblinded_tx.vout):
                    assert len(blinded_tx.vout) == len(unblinded_tx.vout) + 1
                    assert blinded_tx.vout[-1].scriptPubKey == b'\x6a',\
                        "expected last output of blinded tx to be OP_RETURN"
                    scriptPubKey = CScript([OP_RETURN])
                    unblinded_tx = unblinded_tx.to_mutable()
                    unblinded_tx.vout.append(
                        CMutableTxOut(
                            nValue=CConfidentialValue(0),
                            nAsset=CConfidentialAsset(
                                unblinded_tx.vout[-1].nAsset.to_asset()),
                            nNonce=CConfidentialNonce(
                                scriptPubKey.derive_blinding_key(
                                    blinding_derivation_key).pub),
                            scriptPubKey=scriptPubKey))
                    unblinded_tx = unblinded_tx.to_immutable()
                    unblinded_tx_raw = unblinded_tx.serialize()

                self.check_blind(unblinded_tx, unblinded_tx_raw, blinded_tx,
                                 blinded_tx_raw, bundle,
                                 blinding_derivation_key)

                self.check_unblind(unblinded_tx, unblinded_tx_raw, blinded_tx,
                                   blinded_tx_raw, bundle,
                                   blinding_derivation_key)

                self.check_sign(blinded_tx, signed_tx, bundle)
Ejemplo n.º 3
0
    def test_repr(self):
        def T(txout, expected):
            actual = repr(txout)
            self.assertEqual(actual, expected)

        T(CMutableTxOut(1000, CScript(b'\x03abc')),
          "CBitcoinMutableTxOut(0.00001*COIN, CBitcoinScript([x('616263')]))")
Ejemplo n.º 4
0
def mktx(ins, outs, version=1, locktime=0):
    """ Given a list of input tuples (txid(bytes), n(int)),
    and a list of outputs which are dicts with
    keys "address" (value should be *str* not CCoinAddress) (
    or alternately "script" (for nonstandard outputs, value
    should be CScript)),
    "value" (value should be integer satoshis), outputs a
    CMutableTransaction object.
    Tx version and locktime are optionally set, for non-default
    locktimes, inputs are given nSequence as per below comment.
    """
    vin = []
    vout = []
    # This does NOT trigger rbf and mimics Core's standard behaviour as of
    # Jan 2019.
    # Tx creators wishing to use rbf will need to set it explicitly outside
    # of this function.
    if locktime != 0:
        sequence = 0xffffffff - 1
    else:
        sequence = 0xffffffff
    for i in ins:
        outpoint = CMutableOutPoint((i[0][::-1]), i[1])
        inp = CMutableTxIn(prevout=outpoint, nSequence=sequence)
        vin.append(inp)
    for o in outs:
        if "script" in o:
            sPK = o["script"]
        else:
            # note the to_scriptPubKey method is only available for standard
            # address types
            sPK = CCoinAddress(o["address"]).to_scriptPubKey()
        out = CMutableTxOut(o["value"], sPK)
        vout.append(out)
    return CMutableTransaction(vin, vout, nLockTime=locktime, nVersion=version)
Ejemplo n.º 5
0
def generate_transaction(amount, txin_txid, txin_vout, txout_addr,
                         redeem_list):
    txin = CMutableTxIn(COutPoint(txin_txid, txin_vout))
    txout = CMutableTxOut(amount * COIN, txout_addr.addr.to_scriptPubKey())
    witness_script = CScriptWitness(tuple(redeem_list))
    witness = CTxWitness(tuple([CTxInWitness(witness_script)]))
    tx = CMutableTransaction(vin=[txin], vout=[txout], witness=witness)
    return tx
Ejemplo n.º 6
0
    def test_repr(self):
        def T(txout, expected):
            actual = repr(txout)
            self.assertEqual(actual, expected)

        T(
            CMutableTxOut(),
            "CElementsMutableTxOut(CConfidentialValue(x('')), CElementsScript([]), CConfidentialAsset(x('')), CConfidentialNonce(x('')))"
        )
Ejemplo n.º 7
0
    def raw_multisig(self):
        source = self.next_address()
        self.fund_address(source, 0.1)

        # construct transaction manually
        tx_ins = [CMutableTxIn(COutPoint(source.txid, source.vout))]

        keys = [self.next_address().key for _ in range(3)]
        redeem_script = CScript([OP_2, keys[0].pub, keys[1].pub, keys[2].pub, OP_3, OP_CHECKMULTISIG])
        tx_outs = [
            CMutableTxOut(Coin(0.1 - self.fee).satoshi(), redeem_script)]

        tx = CMutableTransaction(tx_ins, tx_outs)

        # sign and submit
        key = source.key
        script = source.address.to_scriptPubKey()

        sig = self._sign(script, tx, 0, Coin(source.value).satoshi(), key)
        tx_ins[0].scriptSig = CScript([sig, key.pub])

        txid = self._send_transaction(tx, [])
        self.log_value("raw-multisig-tx", txid)

        # Redeem Transaction
        tx_ins = [CMutableTxIn(COutPoint(lx(txid), 0))]
        destination = self.next_address()
        tx_outs = [CMutableTxOut(Coin(0.1 - 2 * self.fee).satoshi(), destination.address.to_scriptPubKey())]
        tx = CMutableTransaction(tx_ins, tx_outs)

        # Sign with 2 out of three keys
        sig1 = self._sign(redeem_script, tx, 0, Coin(0.1 - self.fee).satoshi(), keys[0])
        sig3 = self._sign(redeem_script, tx, 0, Coin(0.1 - self.fee).satoshi(), keys[2])

        tx_ins[0].scriptSig = CScript([OP_0, sig1, sig3])

        txid = self._send_transaction(tx, [])
        self.log_value("raw-multisig-redeem-tx", txid)
        self.generate_block()
Ejemplo n.º 8
0
    def op_return(self):
        source = self.next_address("p2pkh")
        self.fund_address(source, 2 * self.fee)

        tx_ins = [CMutableTxIn(COutPoint(source.txid, source.vout))]
        tx_outs = [CMutableTxOut(Coin(self.fee).satoshi(), CScript([OP_RETURN, x("4c6f726420566f6c64656d6f7274")]))]
        tx = CMutableTransaction(tx_ins, tx_outs)

        key = source.key
        script = source.address.to_scriptPubKey()

        sig = self._sign(script, tx, 0, Coin(source.value).satoshi(), key)
        tx_ins[0].scriptSig = CScript([sig, key.pub])

        txid = self._send_transaction(tx, [])
        self.log_value("op-return-tx", txid)
Ejemplo n.º 9
0
    def create_custom_block(self, reward):
        txid, _ = self.fund_address(self.next_address(), 10)
        tx2 = self.proxy.getrawtransaction(lx(txid))

        coinbase = CMutableTransaction()
        coinbase.vin.append(CMutableTxIn(COutPoint(), CScript([self.proxy.getblockcount() + 1])))
        coinbase.vout.append(CMutableTxOut(reward * COIN, self.next_address().address.to_scriptPubKey()))

        prev_block_hash = self.proxy.getblockhash(self.proxy.getblockcount())

        ts = self._next_timestamp()
        self.proxy.call("setmocktime", ts)

        for nonce in range(1000):
            block = CBlock(nBits=0x207fffff, vtx=[coinbase, tx2], hashPrevBlock=prev_block_hash, nTime=ts, nNonce=nonce)
            result = self.proxy.submitblock(block)
            if not result:
                self.log.debug("Chosen nonce: {}".format(nonce))
                break
Ejemplo n.º 10
0
def alice(say, recv, send, die, rpc):
    """A function that implements the logic
    of the first participant of an asset atomic swap"""

    # Issue two asset that we are going to swap to Bob's 1 asset
    asset1_str, asset1_utxo = issue_asset(say, 1.0, rpc)
    asset2_str, asset2_utxo = issue_asset(say, 1.0, rpc)

    # We will need to pay a fee in an asset suitable for this
    fee_utxo = find_utxo_for_fee(say, die, rpc)

    say('Getting change address for fee asset')
    # We don't care for blinding key of change - the node will
    # have it, anyway, and we don't need to unblind the change.
    fee_change_addr, _ = get_dst_addr(say, rpc)

    say('Will use utxo {}:{} (amount: {}) for fee, change will go to {}'.
        format(fee_utxo['txid'], fee_utxo['vout'], fee_utxo['amount'],
               fee_change_addr))

    say('Setting up communication with Bob')

    # Tell Bob that we are ready to communicate
    send('ready')

    # To avoid mempool synchronization problems,
    # in our example Alice is the one in charge of generating test blocks.
    # Bob gives alice txid of his transaction that he wants to be confirmed.
    bob_txid = recv('wait-txid-confirm')

    # Make sure asset issuance transactions are confirmed
    rpc.generatetoaddress(1, rpc.getnewaddress())
    wait_confirm(say, asset1_utxo['txid'], die, rpc)
    wait_confirm(say, asset2_utxo['txid'], die, rpc)
    wait_confirm(say, bob_txid, die, rpc)

    # Make sure Bob is alive and ready to communicate, and send
    # him an offer for two assets
    say('Sending offer to Bob')
    my_offers = [
        AtomicSwapOffer(asset=asset1_str,
                        amount=coins_to_satoshi(asset1_utxo['amount'])),
        AtomicSwapOffer(asset=asset2_str,
                        amount=coins_to_satoshi(asset2_utxo['amount']))
    ]
    send('offer', my_offers)

    bob_offer = recv('offer')

    print_asset_balances(say, my_offers + [bob_offer], rpc)

    say('Bob responded with his offer: {}'.format(bob_offer))

    # We unconditionally accept Bob's offer - his asset is
    # equally worthless as ours :-)

    # Generate an address for Bob to send his asset to.
    dst_addr, blinding_key = get_dst_addr(say, rpc)

    say('Sending my address and assetcommitments for my UTXOs to Bob')
    # Send Bob our address, and the assetcommitments of our UTXOs
    # (but not any other information about our UTXO),
    # so he can construct and blind a partial transaction that
    # will spend his own UTXO, to send his asset to our address.
    assetcommitments = [
        asset1_utxo['assetcommitment'], asset2_utxo['assetcommitment'],
        fee_utxo['assetcommitment']
    ]

    send('addr_and_assetcommitments', (str(dst_addr), assetcommitments))

    partial_tx_bytes = recv('partial_blinded_tx')

    say('Got partial blinded tx of size {} bytes from Bob'.format(
        len(partial_tx_bytes)))

    partial_tx = CTransaction.deserialize(partial_tx_bytes)

    if len(partial_tx.vout) != 1:
        die('unexpected number of outputs in tx from Bob: expected 1, got {}'.
            format(len(partial_tx.vout)))

    result = partial_tx.vout[0].unblind_confidential_pair(
        blinding_key, partial_tx.wit.vtxoutwit[0].rangeproof)

    if result.error:
        die('cannot unblind output that should have been directed to us: {}'.
            format(result.error))

    if result.asset.to_hex() != bob_offer.asset:
        die("asset in partial transaction from Bob {} is not the same "
            "as asset in Bob's initial offer ({})".format(
                result.asset.to_hex(), bob_offer.asset))

    if result.amount != bob_offer.amount:
        die("amount in partial transaction from Bob {} is not the same "
            "as amount in Bob's initial offer ({})".format(
                result.amount, bob_offer.amount))

    say("Asset and amount in partial transaction matches Bob's offer")

    bob_addr_list, bob_assetcommitment = recv('addr_list_and_assetcommitment')

    if len(bob_addr_list) != len(my_offers):
        die('unexpected address list lenth from Bob. expected {}, got {}'.
            format(len(my_offers), len(bob_addr_list)))

    say("Bob's addresses to receive my assets: {}".format(bob_addr_list))

    # Convert Bob's addresses to address objects.
    # If Bob passes invalid address, we die with with exception.
    bob_addr_list = [CCoinAddress(a) for a in bob_addr_list]

    # Add our own inputs and outputs to Bob's partial tx

    # Create new mutable transaction from partial_tx
    tx = partial_tx.to_mutable()

    # We have assetcommitment for the first input,
    # other data is not needed for it.
    # initialize first elements of the arrays with empty/negative data.
    input_descriptors = [
        BlindingInputDescriptor(asset=CAsset(),
                                amount=-1,
                                blinding_factor=Uint256(),
                                asset_blinding_factor=Uint256())
    ]

    # First output is already blinded, fill the slot with empty data
    output_pubkeys = [CPubKey()]

    # But assetcommitments array should start with Bob's asset commitment
    assetcommitments = [x(bob_assetcommitment)]

    # We will add our inputs for asset1 and asset2, and also an input
    # that will be used to pay the fee.

    # Note that the order is important: Bob blinded his transaction
    # with assetcommitments in the order we send them to him,
    # and we should add our inputs in the same order.
    utxos_to_add = (asset1_utxo, asset2_utxo, fee_utxo)

    # Add inputs for asset1 and asset2 and fee_asset and prepare input data
    # for blinding
    for utxo in utxos_to_add:
        # When we create CMutableTransaction and pass CTxIn,
        # it will be converted to CMutableTxIn. But if we append
        # to tx.vin or tx.vout, we need to use mutable versions
        # of the txin/txout classes, or else blinding or signing
        # will fail with error, unable to modify the instances.
        # COutPoint is not modified, though, so we can leave it
        # immutable.
        tx.vin.append(
            CMutableTxIn(
                prevout=COutPoint(hash=lx(utxo['txid']), n=utxo['vout'])))
        input_descriptors.append(
            BlindingInputDescriptor(
                asset=CAsset(lx(utxo['asset'])),
                amount=coins_to_satoshi(utxo['amount']),
                blinding_factor=Uint256(lx(utxo['amountblinder'])),
                asset_blinding_factor=Uint256(lx(utxo['assetblinder']))))

        # If we are supplying asset blinders and assetblinders for
        # particular input, assetcommitment data for that input do
        # not need to be correct. But if we are supplying assetcommitments
        # at all (auxiliary_generators argument to tx.blind()),
        # then all the elements of that array must have correct
        # type (bytes) and length (33). This is a requirement of the original
        # Elements Core API, and python-elementstx requires this, too.
        assetcommitments.append(b'\x00' * 33)

    # Add outputs to give Bob all our assets, and fill output pubkeys
    # for blinding the outputs to Bob's addresses
    for n, offer in enumerate(my_offers):
        tx.vout.append(
            CMutableTxOut(nValue=CConfidentialValue(offer.amount),
                          nAsset=CConfidentialAsset(CAsset(lx(offer.asset))),
                          scriptPubKey=bob_addr_list[n].to_scriptPubKey()))
        output_pubkeys.append(bob_addr_list[n].blinding_pubkey)

    # Add change output for fee asset
    fee_change_amount = (coins_to_satoshi(fee_utxo['amount']) -
                         FIXED_FEE_SATOSHI)
    tx.vout.append(
        CMutableTxOut(nValue=CConfidentialValue(fee_change_amount),
                      nAsset=CConfidentialAsset(fee_asset),
                      scriptPubKey=fee_change_addr.to_scriptPubKey()))
    output_pubkeys.append(fee_change_addr.blinding_pubkey)

    # Add fee output.
    # Note that while we use CConfidentialAsset and CConfidentialValue
    # to specify value and asset, they are not in fact confidential here
    # - they are explicit, because we pass explicit values at creation.
    # You can check if they are explicit or confidential
    # with nValue.is_explicit(). If they are explicit, you can access
    # the unblinded values with nValue.to_amount() and nAsset.to_asset()
    tx.vout.append(
        CMutableTxOut(nValue=CConfidentialValue(FIXED_FEE_SATOSHI),
                      nAsset=CConfidentialAsset(fee_asset)))
    # Add dummy pubkey for non-blinded fee output
    output_pubkeys.append(CPubKey())

    # Our transaction lacks txin witness instances for the added inputs,
    # and txout witness instances for added outputs.
    # If transaction already have witness data attached, transaction
    # serialization code will require in/out witness array length
    # to be equal to vin/vout array length
    # Therefore we need to add dummy txin and txout witnesses for each
    # input and output that we added to transaction
    # we added one input and one output per asset, and an additional
    # input/change-output for fee asset.
    for _ in utxos_to_add:
        tx.wit.vtxinwit.append(CMutableTxInWitness())
        tx.wit.vtxoutwit.append(CMutableTxOutWitness())

    # And one extra dummy txout witness for fee output
    tx.wit.vtxoutwit.append(CMutableTxOutWitness())

    # And blind the combined transaction
    blind_result = tx.blind(input_descriptors=input_descriptors,
                            output_pubkeys=output_pubkeys,
                            auxiliary_generators=assetcommitments)

    # The blinding must succeed!
    if blind_result.error:
        die('blind failed: {}'.format(blind_result.error))

    # And must blind exactly three outputs (two to Bob, one fee asset change)
    if blind_result.num_successfully_blinded != 3:
        die('blinded {} outputs, expected to be 3'.format(
            blind_result.num_successfully_blinded))

    say('Successfully blinded the combined transaction, will now sign')

    # Sign two new asset inputs, and fee asset input
    for n, utxo in enumerate(utxos_to_add):
        # We specify input_index as 1+n because we skip first (Bob's) input
        sign_input(tx, 1 + n, utxo)

    say('Signed my inputs, sending partially-signed transaction to Bob')

    send('partially_signed_tx', tx.serialize())

    # Note that at this point both participants can still opt out of the swap:
    # Alice by double-spending her inputs to the transaction,
    # and Bob by not signing or not broadcasting the transaction.
    # Bob still have tiny advantage, because
    # he can pretend to have 'difficulties' in broadcasting and try to exploit
    # Alice's patience. If Alice does not reclaim her funds in the case Bob's
    # behaviour deviates from expected, then Bob will have free option to
    # exectute the swap at the time convenient to him.

    # Get the swap transaction from Bob.
    # Bob is expected to broadcast this transaction, and could just send txid
    # here, but then there would be a period of uncertainty: if Alice do not
    # see the txid at her own node, she does not know if this is because Bob
    # did not actually broadcast, and is just taking his time watching asset
    # prices, or the transaction just takes long time to propagate. If the
    # protocol requires Bob to send the transaction, the timeout required for
    # Alice to wait can be defined much more certainly.
    try:
        signed_tx_raw = recv('final-signed-tx', timeout=ALICE_PATIENCE_LIMIT)
        signed_tx = CTransaction.deserialize(x(signed_tx_raw))
        # Check that this transaction spends the same inputs as the transacton
        # previously agreed upon
        for n, vin in enumerate(signed_tx.vin):
            if vin.prevout != tx.vin[n].prevout:
                die('Inputs of transaction received from Bob do not match '
                    'the agreed-upon transaction')
        # Send the transaction from our side
        txid = rpc.sendrawtransaction(b2x(signed_tx.serialize()))
    except Exception as e:
        # If there is any problem, including communication timeout or invalid
        # communication, or invalid transaction encoding, then Alice will try
        # to claim her funds back, so Bob won't have an option to execute the
        # swap at the time convenient to him. He should execute it immediately.
        say('Unexpected problem on receiving final signed transaction '
            'from Bob: {}'.format(e))
        say('This is suspicious. I will try to reclaim my funds now')
        claim_funds_back(say, utxos_to_add, die, rpc)
        say("Claimed my funds back. Screw Bob!")
        sys.exit(0)

    # Make sure the final transaction is confirmed
    rpc.generatetoaddress(1, rpc.getnewaddress())
    wait_confirm(say, txid, die, rpc)

    # Check that everything went smoothly
    balance = coins_to_satoshi(rpc.getbalance("*", 1, False, bob_offer.asset))
    if balance != bob_offer.amount:
        die('something went wrong, balance of Bob\'s asset after swap '
            'should be {} satoshi, but it is {} satoshi'.format(
                balance, bob_offer.amount))

    print_asset_balances(say, my_offers + [bob_offer], rpc)

    # Wait for alice to politely end the conversation
    send('thanks-goodbye')

    say('Asset atomic swap completed successfully')
Ejemplo n.º 11
0
 def test_mutable(self):
     """CTxIn shall be mutable"""
     txout = CMutableTxOut()
     txout.nValue = None
Ejemplo n.º 12
0
#
# lx() takes *little-endian* hex and converts it to bytes; in Bitcoin
# transaction hashes are shown little-endian rather than the usual big-endian.
# There's also a corresponding x() convenience function that takes big-endian
# hex and converts it to bytes.
txid = lx('bff785da9f8169f49be92fa95e31f0890c385bfb1bd24d6b94d7900057c617ae')
vout = 0

# Create the txin structure, which includes the outpoint. The scriptSig
# defaults to being empty.
txin = CMutableTxIn(COutPoint(txid, vout))

# Create the txout. This time we create the scriptPubKey from a Bitcoin
# address.
txout = CMutableTxOut(
    coins_to_satoshi(0.0005),
    CBitcoinAddress('323uf9MgLaSn9T7vDaK1cGAZ2qpvYUuqSp').to_scriptPubKey())

# Create the unsigned transaction.
tx = CMutableTransaction([txin], [txout])

# Calculate the signature hash for that transaction. Note how the script we use
# is the redeemScript, not the scriptPubKey. That's because when the CHECKSIG
# operation happens EvalScript() will be evaluating the redeemScript, so the
# corresponding SignatureHash() function will use that same script when it
# replaces the scriptSig in the transaction being hashed with the script being
# executed.
sighash = SignatureHash(txin_redeemScript, tx, 0, SIGHASH_ALL)

# Now sign it. We have to append the type of signature we want to the end, in
# this case the usual SIGHASH_ALL.
Ejemplo n.º 13
0
 def test_clone(self):
     txout = CMutableTxOut(1000, CScript(b'\x03abc'))
     self.assertEqual(txout.serialize(), txout.clone().serialize())
Ejemplo n.º 14
0
            continue

    for digest in digests:
        txouts = []

        unspent = sorted(rpc.listunspent(0), key=lambda x: hash(x['amount']))

        txins = [
            CTxIn(COutPoint(lx(unspent[-1]['txid']), int(unspent[-1]['vout'])))
        ]
        value_in = coins_to_satoshi(unspent[-1]['amount'])

        change_addr = rpc.getnewaddress()
        change_pubkey_hex = rpc.getaddressinfo(change_addr)['pubkey']
        change_out = CMutableTxOut(
            CoreCoinParams.MAX_MONEY,
            CScript([x(change_pubkey_hex), OP_CHECKSIG]))

        digest_outs = [CMutableTxOut(0, CScript([OP_RETURN, digest]))]

        txouts = [change_out] + digest_outs

        tx = CTransaction(txins, txouts).to_mutable()

        FEE_PER_VBYTE = 0.00025 * CoreCoinParams.COIN / 1000
        while True:
            required_fee = tx.get_virtual_size() * FEE_PER_VBYTE
            tx.vout[0].nValue = int(value_in -
                                    max(required_fee, 0.00011 *
                                        CoreCoinParams.COIN))
Ejemplo n.º 15
0
    def _create_transaction(self, sources: List[Address],
                            recipients: List[Address], values, n_locktime,
                            n_sequence):
        # save cospends
        self.cospends.union_all([str(x.address) for x in sources])

        if not values:
            values = [recipient.value for recipient in recipients]
        tx_ins = [
            CMutableTxIn(COutPoint(source.txid, source.vout),
                         nSequence=n_sequence) for source in sources
        ]
        tx_outs = []

        cnt = 0
        for recipient, value in zip(recipients, values):
            if value == 0:
                self.log.warning("Creating output with 0 BTC")
            recipient.vout = cnt

            tx_outs.append(
                CMutableTxOut(
                    Coin(value).satoshi(),
                    recipient.address.to_scriptPubKey()))
            cnt += 1

        tx = CMutableTransaction(tx_ins, tx_outs, nLockTime=n_locktime)

        in_idx = 0
        witnesses = []
        for txin, source in zip(tx_ins, sources):
            key = source.key

            if source.type == 'p2pkh':
                script = source.address.to_redeemScript()
            elif source.type == 'p2sh':
                script = CScript([key.pub, OP_CHECKSIG])
            elif source.type == 'p2wpkh':
                script = source.address.to_redeemScript()
            elif source.type == 'p2wsh':
                script = source.witness_program
            else:
                raise UnsupportedAddressTypeError()

            # Create signature
            amount = Coin(source.value).satoshi()
            sig = self._sign(script, tx, in_idx, amount, key, source.type)

            # Add signature to input or witness
            if source.type == 'p2pkh':
                txin.scriptSig = CScript([sig, key.pub])
                witnesses.append(CTxInWitness())
            elif source.type == 'p2sh':
                txin.scriptSig = CScript([sig, script])
                witnesses.append(CTxInWitness())
            elif source.type == 'p2wpkh':
                txin.scriptSig = CScript()
                witnesses.append(CTxInWitness(CScriptWitness([sig, key.pub])))
            elif source.type == 'p2wsh':
                txin.scriptSig = CScript()
                witnesses.append(CTxInWitness(CScriptWitness([sig, script])))
            in_idx += 1

        tx.wit = CTxWitness(witnesses)
        return tx
Ejemplo n.º 16
0
#
# lx() takes *little-endian* hex and converts it to bytes; in Bitcoin
# transaction hashes are shown little-endian rather than the usual big-endian.
# There's also a corresponding x() convenience function that takes big-endian
# hex and converts it to bytes.
txid = lx('bff785da9f8169f49be92fa95e31f0890c385bfb1bd24d6b94d7900057c617ae')
vout = 0

# Create the txin structure, which includes the outpoint. The scriptSig
# defaults to being empty.
txin = CMutableTxIn(COutPoint(txid, vout))

# Create the txout. This time we create the scriptPubKey from a Bitcoin
# address.
txout = CMutableTxOut(0.0005*COIN,
                      CBitcoinAddress(
                          '323uf9MgLaSn9T7vDaK1cGAZ2qpvYUuqSp'
                      ).to_scriptPubKey())

# Create the unsigned transaction.
tx = CMutableTransaction([txin], [txout])

# Calculate the signature hash for that transaction. Note how the script we use
# is the redeemScript, not the scriptPubKey. That's because when the CHECKSIG
# operation happens EvalScript() will be evaluating the redeemScript, so the
# corresponding SignatureHash() function will use that same script when it
# replaces the scriptSig in the transaction being hashed with the script being
# executed.
sighash = SignatureHash(txin_redeemScript, tx, 0, SIGHASH_ALL)

# Now sign it. We have to append the type of signature we want to the end, in
# this case the usual SIGHASH_ALL.
Ejemplo n.º 17
0
# Create the txin structure, which includes the outpoint. The scriptSig
# defaults to being empty.
txin = CMutableTxIn(COutPoint(txid, vout))

# We also need the scriptPubKey of the output we're spending because
# SignatureHash() replaces the transaction scriptSig's with it.
#
# Here we'll create that scriptPubKey from scratch using the pubkey that
# corresponds to the secret key we generated above.
txin_scriptPubKey = \
    P2PKHBitcoinAddress.from_pubkey(seckey.pub).to_scriptPubKey()

# Create the txout. This time we create the scriptPubKey from a Bitcoin
# address.
txout = CMutableTxOut(
    0.001 * COIN,
    CBitcoinAddress('1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8').to_scriptPubKey())

# Create the unsigned transaction.
tx = CMutableTransaction([txin], [txout])

# Calculate the signature hash for that transaction.
sighash = SignatureHash(txin_scriptPubKey, tx, 0, SIGHASH_ALL)

# Now sign it. We have to append the type of signature we want to the end, in
# this case the usual SIGHASH_ALL.
sig = seckey.sign(sighash) + bytes([SIGHASH_ALL])

# Set the scriptSig of our transaction input appropriately.
txin.scriptSig = CScript([sig, seckey.pub])
Ejemplo n.º 18
0
# Create the txin structure, which includes the outpoint. The scriptSig
# defaults to being empty.
txin = CMutableTxIn(COutPoint(txid, vout))

# We also need the scriptPubKey of the output we're spending because
# SignatureHash() replaces the transaction scriptSig's with it.
#
# Here we'll create that scriptPubKey from scratch using the pubkey that
# corresponds to the secret key we generated above.
txin_scriptPubKey = \
    P2PKHBitcoinAddress.from_pubkey(seckey.pub).to_scriptPubKey()

# Create the txout. This time we create the scriptPubKey from a Bitcoin
# address.
txout = CMutableTxOut(
    coins_to_satoshi(0.001),
    CBitcoinAddress('1C7zdTfnkzmr13HfA2vNm5SJYRK6nEKyq8').to_scriptPubKey())

# Create the unsigned transaction.
tx = CMutableTransaction([txin], [txout])

# Calculate the signature hash for that transaction.
sighash = SignatureHash(txin_scriptPubKey, tx, 0, SIGHASH_ALL)

# Now sign it. We have to append the type of signature we want to the end, in
# this case the usual SIGHASH_ALL.
sig = seckey.sign(sighash) + bytes([SIGHASH_ALL])

# Set the scriptSig of our transaction input appropriately.
txin.scriptSig = CScript([sig, seckey.pub])