Beispiel #1
0
def test_signature_hash(filename):
    tx, values, pk_scripts = read_json_tx(filename)
    correct_hashes = read_signature_hashes(
        filename.replace('.txn', '.sig_hashes'))

    n = 0
    for input_index, (value, pk_script,
                      txin) in enumerate(zip(values, pk_scripts, tx.inputs)):
        for sighash in range(256):
            sighash = SigHash(sighash)
            if sighash.has_forkid():
                signature_hash = tx.signature_hash(input_index, value,
                                                   pk_script, sighash)
                assert signature_hash == correct_hashes[n]
            n += 1
    def test_issue(priv_key,
                   receiver,
                   new_issuer=issuer,
                   next_tok_id=curr_token_id + 1,
                   issued_tok_id=curr_token_id):
        context = scryptlib.utils.create_dummy_input_context()
        context.utxo.script_pubkey = token.locking_script
        context.utxo.value = input_sats

        new_data_part = b'\x23' + scryptlib.utils.get_push_int(next_tok_id)[1:] + \
                        new_issuer.to_bytes() + action_issue
        new_locking_script = Script(token.code_part.to_bytes() + new_data_part)
        tx_out = TxOutput(value=out_sats, script_pubkey=new_locking_script)
        context.tx.outputs.append(tx_out)

        new_data_part = b'\x23' + scryptlib.utils.get_push_int(issued_tok_id)[1:] + \
                        receiver.to_bytes() + action_transfer
        new_locking_script = Script(token.code_part.to_bytes() + new_data_part)
        tx_out = TxOutput(value=out_sats, script_pubkey=new_locking_script)
        context.tx.outputs.append(tx_out)

        sighash_flag = SigHash(SigHash.ALL | SigHash.FORKID)
        sighash = context.tx.signature_hash(0, input_sats,
                                            token.locking_script, sighash_flag)
        sig = priv_key.sign(sighash, hasher=None)
        sig = sig + pack_byte(sighash_flag)

        preimage = scryptlib.utils.get_preimage_from_input_context(
            context, sighash_flag)

        return token.issue(Sig(sig), PubKey(receiver), out_sats, out_sats,
                           SigHashPreimage(preimage)).verify(context)
Beispiel #3
0
 def preimage_hash(self, txin):
     input_index = self.inputs.index(txin)
     script_code = bytes.fromhex(self.get_preimage_script(txin))
     sighash = SigHash(self.nHashType())
     # Original BTC algorithm: https://en.bitcoin.it/wiki/OP_CHECKSIG
     # Current algorithm: https://github.com/moneybutton/bips/blob/master/bip-0143.mediawiki
     return self.signature_hash(input_index, txin.value, script_code, sighash=sighash)
def test_verify_scenario_2():
    context = scryptlib.utils.create_dummy_input_context()
    context.utxo.script_pubkey = escrow.locking_script
    context.utxo.value = input_sats

    change_out = TxOutput(int(input_sats - fee),
                          P2PKH_Address(pkh_A, Bitcoin).to_script())
    context.tx.outputs.append(change_out)

    sighash_flag = SigHash(SigHash.ALL | SigHash.FORKID)
    sighash = context.tx.signature_hash(0, input_sats, escrow.locking_script,
                                        sighash_flag)

    sig_A = key_priv_A.sign(sighash, hasher=None)
    sig_A = sig_A + pack_byte(sighash_flag)

    sig_E = key_priv_E.sign(sighash, hasher=None)
    sig_E = sig_E + pack_byte(sighash_flag)

    preimage = scryptlib.utils.get_preimage_from_input_context(
        context, sighash_flag)

    verify_result = escrow.unlock(SigHashPreimage(preimage), PubKey(key_pub_A),
                                  Sig(sig_A), PubKey(key_pub_E), Sig(sig_E),
                                  Bytes(secret0)).verify(context)
    assert verify_result == True

    # Wrong secret
    with pytest.raises(bitcoinx.VerifyFailed):
        verify_result = escrow.unlock(SigHashPreimage(preimage),
                                      PubKey(key_pub_A), Sig(sig_A),
                                      PubKey(key_pub_E), Sig(sig_E),
                                      Bytes(secret1)).verify(context)
Beispiel #5
0
def get_preimage(tx, input_index, utxo_value, utxo_script, sighash_flag=None):
    if not sighash_flag:
        sighash_flag = SigHash(SigHash.ALL | SigHash.FORKID)

    txin = tx.inputs[input_index]
    hash_prevouts = hash_sequence = hash_outputs = bitcoinx.consts.ZERO

    sighash_not_single_none = sighash_flag.base not in (SigHash.SINGLE, SigHash.NONE)
    if not sighash_flag.anyone_can_pay:
        hash_prevouts = tx._hash_prevouts()
        if sighash_not_single_none:
            hash_sequence = tx._hash_sequence()
    if sighash_not_single_none:
        hash_outputs = tx._hash_outputs()
    elif (sighash_flag.base == SigHash.SINGLE and input_index < len(tx.outputs)):
        hash_outputs = double_sha256(tx.outputs[input_index].to_bytes())

    preimage = b''.join((
        pack_le_int32(tx.version),
        hash_prevouts,
        hash_sequence,
        txin.to_bytes_for_signature(utxo_value, utxo_script),
        hash_outputs,
        pack_le_uint32(tx.locktime),
        pack_le_uint32(sighash_flag),
    ))
    return preimage
def test_verify_with_change():
    deposit_sats = 100000
    input_sats = 100000
    output_sats = deposit_sats + input_sats
    change_sats = 547

    faucet.set_data_part(scryptlib.utils.get_push_int(1602553516))

    context = scryptlib.utils.create_dummy_input_context()
    context.utxo.script_pubkey = faucet.locking_script
    context.utxo.value = input_sats

    tx_out_0 = TxOutput(value=output_sats, script_pubkey=faucet.locking_script)
    context.tx.outputs.append(tx_out_0)

    tx_out_1 = TxOutput(value=change_sats,
                        script_pubkey=P2PKH_Address(pkh, Bitcoin).to_script())
    context.tx.outputs.append(tx_out_1)

    sighash_flag = SigHash(SigHash.ALL | SigHash.FORKID)
    preimage = scryptlib.utils.get_preimage_from_input_context(
        context, sighash_flag)

    verify_result = faucet.deposit(SigHashPreimage(preimage), deposit_sats,
                                   Ripemd160(pkh), change_sats).verify(context)
    assert verify_result == True

    with pytest.raises(bitcoinx.VerifyFailed):
        faucet.deposit(SigHashPreimage(preimage), deposit_sats, Ripemd160(pkh),
                       change_sats + 1).verify(context)
Beispiel #7
0
 def preimage_hash(self, txin):
     input_index = self.inputs.index(txin)
     script_code = bytes.fromhex(self.get_preimage_script(txin))
     sighash = SigHash(self.nHashType())
     return self.signature_hash(input_index,
                                txin.value,
                                script_code,
                                sighash=sighash)
Beispiel #8
0
def test_verify_p2pkh_correct():
    context = scryptlib.utils.create_dummy_input_context()
    sighash_flag = SigHash(SigHash.ALL | SigHash.FORKID)
    sighash = context.tx.signature_hash(0, context.utxo.value,
                                        asm.locking_script, sighash_flag)
    sig = key_priv.sign(sighash, hasher=None)
    sig = sig + pack_byte(sighash_flag)
    verify_result = asm.p2pkh(Sig(sig), PubKey(key_pub)).verify(context)
    assert verify_result == True
Beispiel #9
0
def get_preimage_from_input_context(context, sighash_flag=None):
    if not sighash_flag:
        sighash_flag = SigHash(SigHash.ALL | SigHash.FORKID)

    tx = context.tx
    input_index = context.input_index
    utxo_value = context.utxo.value
    utxo_script = context.utxo.script_pubkey
    return get_preimage(tx, input_index, utxo_value, utxo_script, sighash_flag)
Beispiel #10
0
def increment_counter(counter_obj, prev_txid, prev_out_idx, funding_txid,
                      funding_out_idx, unlock_key_priv, miner_fee):
    # Get data from previous counter tx
    r = requests.get('https://api.whatsonchain.com/v1/bsv/main/tx/{}'.format(
        prev_txid)).json()
    prev_locking_script = Script.from_hex(
        r['vout'][prev_out_idx]['scriptPubKey']['hex'])
    prev_counter_bytes = list(prev_locking_script.ops())[-1]
    prev_counter_val = int.from_bytes(prev_counter_bytes, 'little')
    unlocked_satoshis_counter = int(r['vout'][prev_out_idx]['value'] * 10**8)

    # Get data from funding tx
    r = requests.get('https://api.whatsonchain.com/v1/bsv/main/tx/{}'.format(
        funding_txid)).json()
    funding_locking_script = Script.from_hex(
        r['vout'][funding_out_idx]['scriptPubKey']['hex'])
    unlocked_satoshis_funding = int(r['vout'][funding_out_idx]['value'] *
                                    10**8)

    # Set data for next iteration
    counter_obj.set_data_part(
        scryptlib.utils.get_push_int(prev_counter_val + 1))

    ## Construct tx
    n_sequence = 0xffffffff

    # Counter input and output
    prev_tx_hash = hex_str_to_hash(prev_txid)
    counter_in = TxInput(prev_tx_hash, prev_out_idx, None, n_sequence)
    out_satoshis = unlocked_satoshis_counter + unlocked_satoshis_funding - miner_fee
    contract_out = TxOutput(out_satoshis, counter_obj.locking_script)

    # Funding input
    funding_tx_hash = hex_str_to_hash(funding_txid)
    funding_in = TxInput(funding_tx_hash, funding_out_idx, None, n_sequence)

    tx = Tx(2, [counter_in, funding_in], [contract_out], 0x00000000)

    # Set input script to unlock previous counter
    sighash_flag = SigHash(SigHash.ALL | SigHash.FORKID)
    preimage = scryptlib.utils.get_preimage(tx, 0, unlocked_satoshis_counter,
                                            prev_locking_script, sighash_flag)
    increment_func_call = counter_obj.increment(SigHashPreimage(preimage),
                                                Int(out_satoshis))
    tx.inputs[0].script_sig = increment_func_call.script

    # Set input script to unlock funding output
    unlock_key_pub = unlock_key_priv.public_key
    sighash = tx.signature_hash(1, unlocked_satoshis_funding,
                                funding_locking_script, sighash_flag)
    sig = unlock_key_priv.sign(sighash, hasher=None)
    sig = sig + pack_byte(sighash_flag)
    unlock_script = Script() << sig << unlock_key_pub.to_bytes()
    tx.inputs[1].script_sig = unlock_script

    broadcast_tx(tx)
Beispiel #11
0
def test_signatures(filename):
    tx, values, pk_scripts = read_json_tx(filename)

    for input_index, (value, pk_script,
                      txin) in enumerate(zip(values, pk_scripts, tx.inputs)):
        signature, pubkey = txin.script_sig.ops()
        pubkey = PublicKey.from_bytes(pubkey)
        signature_hash = tx.signature_hash(input_index, value, pk_script,
                                           SigHash(signature[-1]))
        assert pubkey.verify_der_signature(signature[:-1], signature_hash,
                                           None)
Beispiel #12
0
def test_verify_wrong_output():
    context = scryptlib.utils.create_dummy_input_context()
    context.utxo.script_pubkey = gol.locking_script

    new_locking_script = Script(gol.code_part.to_bytes() + wb1)
    tx_out = TxOutput(value=out_amount, script_pubkey=new_locking_script)
    context.tx.outputs.append(tx_out)

    sighash_flag = SigHash(SigHash.ALL | SigHash.FORKID)
    preimage = scryptlib.utils.get_preimage_from_input_context(context, sighash_flag)

    verify_result = gol.play(out_amount, SigHashPreimage(preimage)).verify(context)
    assert verify_result == False
Beispiel #13
0
def test_signature_hash_bad():
    tx, _, _ = read_json_tx('503fd37f.txn')

    with pytest.raises(IndexError):
        tx.signature_hash(-1, 5, b'', SigHash.ALL)
    with pytest.raises(IndexError):
        tx.signature_hash(2, 5, b'', SigHash.ALL)
    with pytest.raises(ValueError):
        tx.signature_hash(0, -1, b'', SigHash.ALL)
    with pytest.raises(TypeError):
        tx.signature_hash(0, 0, b'', 1)
    tx.signature_hash(0, 0, b'', SigHash.NONE)
    tx.signature_hash(1, 0, b'', SigHash(1))
Beispiel #14
0
    def test_merge(input_idx, balance0, balance1):
        context = scryptlib.utils.create_dummy_input_context()
        context.utxo.value = in_sats
        context.input_index = input_idx

        tx_in = TxInput(context.tx.inputs[0].prev_hash, 1, Script(), 0xffffffff)
        context.tx.inputs.append(tx_in)

        prev_txid = context.tx.inputs[0].prev_hash
        prevouts = prev_txid + b'\x00\x00\x00\x00' + prev_txid + b'\x01\x00\x00\x00'

        new_locking_script = Script(token.code_part.to_bytes() + b'\x23' +
                key_pub_2.to_bytes() + scryptlib.utils.get_push_int(balance0)[1:] + scryptlib.utils.get_push_int(balance1)[1:])
        tx_out = TxOutput(value=out_sats, script_pubkey=new_locking_script)
        context.tx.outputs.append(tx_out)

        if input_idx == 0:
            balance = balance1
            context.utxo.script_pubkey = locking_script_0
            key_to_sign = key_priv_0
            token.set_data_part(b'\x23' + data_part_0)
        else:
            balance = balance0
            context.utxo.script_pubkey = locking_script_1
            key_to_sign = key_priv_1
            token.set_data_part(b'\x23' + data_part_1)

        sighash_flag = SigHash(SigHash.ALL | SigHash.FORKID)
        #preimage = scryptlib.utils.get_preimage_from_input_context(context, sighash_flag)
        if input_idx == 0:
            preimage = scryptlib.utils.get_preimage(context.tx, input_idx, in_sats, locking_script_0, sighash_flag=sighash_flag)
        else:
            preimage = scryptlib.utils.get_preimage(context.tx, input_idx, in_sats, locking_script_1, sighash_flag=sighash_flag)

        if input_idx == 0:
            sighash = context.tx.signature_hash(input_idx, in_sats, locking_script_0, sighash_flag)
        else:
            sighash = context.tx.signature_hash(input_idx, in_sats, locking_script_1, sighash_flag)
        sig = key_to_sign.sign(sighash, hasher=None)
        sig = sig + pack_byte(sighash_flag)


        return token.merge(
                    Sig(sig),
                    PubKey(key_pub_2),
                    Bytes(prevouts),
                    balance,
                    out_sats,
                    SigHashPreimage(preimage)
                ).verify(context)
Beispiel #15
0
def test_verify_incorrect_sat_amount():
    context = scryptlib.utils.create_dummy_input_context()
    context.utxo.script_pubkey = counter_obj.locking_script

    subsequent_counter_val_bytes = scryptlib.utils.get_push_int(COUNTER_INITIAL_VAL + 1)
    new_locking_script = counter_obj.code_part << Script(subsequent_counter_val_bytes)
    tx_out = TxOutput(value=0, script_pubkey=new_locking_script)
    context.tx.outputs.append(tx_out)

    sighash_flag = SigHash(SigHash.ALL | SigHash.FORKID)
    preimage = scryptlib.utils.get_preimage_from_input_context(context, sighash_flag)
    new_output_satoshis = 100
    verify_result = counter_obj.increment(SigHashPreimage(preimage), Int(new_output_satoshis)).verify(context)
    assert verify_result == False
Beispiel #16
0
def test_sighash(execution_count):
    '''Tests the original Satoshi signature_hash on random transactions.'''
    hash_type = random.randrange(0, 1 << 32)
    sighash_type = SigHash(hash_type)

    tx = random_tx((hash_type & 0x1f) == SigHash.SINGLE)
    script_code = random_script()
    input_index = random.randrange(0, len(tx.inputs))

    live_hash = tx._original_signature_hash(input_index, script_code,
                                            sighash_type)

    # ref_sighash modifies the tx so do it second
    ref_hash = ref_sighash(script_code, tx, input_index, hash_type)

    assert live_hash == ref_hash
def test_verify_correct_constructor():
    context = scryptlib.utils.create_dummy_input_context()
    context.utxo.script_pubkey = counter_obj.locking_script

    new_locking_script = counter_obj.get_state_script(
        {"counter": COUNTER_INITIAL_VAL + 1})

    tx_out = TxOutput(value=0, script_pubkey=new_locking_script)
    context.tx.outputs.append(tx_out)

    sighash_flag = SigHash(SigHash.ALL | SigHash.FORKID)
    preimage = scryptlib.utils.get_preimage_from_input_context(
        context, sighash_flag)
    new_output_satoshis = 0
    verify_result = counter_obj.unlock(
        SigHashPreimage(preimage), Int(new_output_satoshis)).verify(context)
    assert verify_result == True
Beispiel #18
0
    def test_split(key_priv, balance0, balance1, balance_input0=None, balance_input1=None):
        if not balance_input0:
            balance_input0 = balance0
        if not balance_input1:
            balance_input1 = balance1

        context = scryptlib.utils.create_dummy_input_context()
        context.utxo.script_pubkey = token.locking_script
        context.utxo.value = in_sats
            
        new_locking_script = Script(token.code_part.to_bytes() + b'\x23' +
                key_pub_1.to_bytes() + b'\x00' + scryptlib.utils.get_push_int(balance0)[1:])
        tx_out = TxOutput(value=out_sats, script_pubkey=new_locking_script)
        context.tx.outputs.append(tx_out)

        if balance1 > 0:
            new_locking_script = Script(token.code_part.to_bytes() + b'\x23' + 
                    key_pub_2.to_bytes() + b'\x00' + scryptlib.utils.get_push_int(balance1)[1:])
            tx_out = TxOutput(value=out_sats, script_pubkey=new_locking_script)
            context.tx.outputs.append(tx_out)

        sighash_flag = SigHash(SigHash.ALL | SigHash.FORKID)
        preimage = scryptlib.utils.get_preimage_from_input_context(context, sighash_flag)

        input_idx = 0
        utxo_satoshis = context.utxo.value
        sighash = context.tx.signature_hash(input_idx, utxo_satoshis, token.locking_script, sighash_flag)
        sig = key_priv.sign(sighash, hasher=None)
        sig = sig + pack_byte(sighash_flag)

        return token.split(
                    Sig(sig),
                    PubKey(key_pub_1),
                    balance_input0,
                    out_sats,
                    PubKey(key_pub_2),
                    balance_input1,
                    out_sats,
                    SigHashPreimage(preimage)
                ).verify(context)
Beispiel #19
0
def initialize_counter(counter_obj, counter_initial_val, funding_txid, funding_out_idx, \
        unlock_key_priv, miner_fee, contract_out_sats, change_addr):
    counter_obj.set_data_part(
        scryptlib.utils.get_push_int(counter_initial_val))

    # Funding TX
    funding_tx_hash = hex_str_to_hash(funding_txid)
    unlock_key_pub = unlock_key_priv.public_key

    r = requests.get('https://api.whatsonchain.com/v1/bsv/main/tx/{}'.format(
        funding_txid)).json()
    funding_locking_script = Script.from_hex(
        r['vout'][funding_out_idx]['scriptPubKey']['hex'])
    unlocked_satoshis = int(r['vout'][funding_out_idx]['value'] * 10**8)
    n_sequence = 0xffffffff
    tx_input = TxInput(funding_tx_hash, funding_out_idx, None, n_sequence)

    # Output with counter script code
    contract_out = TxOutput(contract_out_sats, counter_obj.locking_script)

    # Change output
    tx_output_script = P2PKH_Address.from_string(change_addr,
                                                 Bitcoin).to_script()
    change_out = TxOutput(unlocked_satoshis - miner_fee - contract_out_sats,
                          tx_output_script)

    tx = Tx(2, [tx_input], [contract_out, change_out], 0x00000000)

    # Create signature for input
    sighash_flag = SigHash(SigHash.ALL | SigHash.FORKID)
    sighash = tx.signature_hash(0, unlocked_satoshis, funding_locking_script,
                                sighash_flag)
    sig = unlock_key_priv.sign(sighash, hasher=None)
    sig = sig + pack_byte(sighash_flag)

    # Set script for input
    unlock_script = Script() << sig << unlock_key_pub.to_bytes()
    tx.inputs[0].script_sig = unlock_script

    broadcast_tx(tx)
pubkey_hash = key_pub.hash160()

wrong_key_priv = PrivateKey.from_arbitrary_bytes(b'somethingelse')
wrong_key_pub = wrong_key_priv.public_key

contract = './test/res/p2pkh.scrypt'

compiler_result = scryptlib.utils.compile_contract(contract)
desc = compiler_result.to_desc()

P2PKH = scryptlib.contract.build_contract_class(desc)
p2pkh_obj = P2PKH(PubKeyHash(pubkey_hash))

context = scryptlib.utils.create_dummy_input_context()

sighash_flag = SigHash(SigHash.ALL | SigHash.FORKID)
input_idx = 0
utxo_satoshis = context.utxo.value
sighash = context.tx.signature_hash(input_idx, utxo_satoshis,
                                    p2pkh_obj.locking_script, sighash_flag)


def test_verify_correct_key():
    sig = key_priv.sign(sighash, hasher=None)
    sig = sig + pack_byte(sighash_flag)
    verify_result = p2pkh_obj.unlock(Sig(sig), PubKey(key_pub)).verify(context)
    assert verify_result == True


def test_verify_wrong():
    sig = wrong_key_priv.sign(sighash, hasher=None)
payout_addr = pkh
change_addr = pkh

contract = './test/res/merkleToken.scrypt'

compiler_result = scryptlib.utils.compile_contract(contract)
desc = compiler_result.to_desc()

input_sats = 100000
sat_price = 100
Token = scryptlib.contract.build_contract_class(desc)
token = Token(sat_price)

change_sats = 100

sighash_flag = SigHash(SigHash.ANYONE_CAN_PAY | SigHash.ALL | SigHash.FORKID)

#def test_verify_buy_token():
#    amount = 1
#    new_entry = payout_addr + scryptlib.utils.get_push_int(amount)[1:]
#    last_entry = b'\x00' * 20 + b'\x01'
#
#    last_entry_hash = hashlib.sha256(last_entry).digest()
#    new_entry_hash = hashlib.sha256(new_entry).digest()
#
#    mixhash = hashlib.sha256(last_entry_hash + new_entry_hash).digest()
#    new_locking_script = token.code_part << Script(b'\x23' + scryptlib.utils.get_push_item(mixhash))
#    last_merkle_path = Bytes(last_entry_hash + b'\x01')
#
#    last_entry_double_hash = hashlib.sha256(last_entry_hash * 2).digest()
#    token.set_data_part(scryptlib.utils.get_push_item(last_entry_double_hash))