def make_synthetic_vin(transaction, vin_index):
    """
    make a vin object 
    """
    vin = {}

    # get a transaction fragment to consume from HeliumDB
    # get some random block earlier then our consuming block
    #        select a random vout element
    #        check Heliumb to see if output spent
    #        if not add it

    # get a transaction fragment to consume

    for ctr in range(10):

        if wfragment["spent"] == False: break
        if ctr == 10: return False  # could not get any inputs

    vin['txid'] = wfragment["transactionid"]
    vin['vout_index'] = wfragment["vout_index"]

    keys = tx_keys[wfragment["transactionid"]]

    vin['ScriptSig'] = []
    vin["ScriptSig"].append(rcrypt.sign_message(keys[0], keys[1]))
    vin["ScriptSig"].append(keys[1])

    return vin
def test_sign_message(message, value):
    """
    Digitally sign a message and then verify it
    """
    ecc_tuple = rcrypt.make_ecc_keys()
    priv_key = ecc_tuple[0]
    pub_key = ecc_tuple[1]

    sig = rcrypt.sign_message(priv_key, message)

    ret = rcrypt.verify_signature(pub_key, message, sig)
    assert ret == value
Пример #3
0
def make_random_transaction(block_height):

    tx = {}
    tx["version"] = "1"
    tx["transactionid"] = rcrypt.make_uuid()
    tx["locktime"] = secrets.randbelow(hconfig.conf["MAX_LOCKTIME"])

    # public-private key pair for previous transaction
    prev_keys = rcrypt.make_ecc_keys()

    # public-private key pair for this transaction
    keys = rcrypt.make_ecc_keys()

    # Build vin
    tx["vin"] = []

    if block_height > 0:
        ctr = secrets.randbelow(hconfig.conf["MAX_INPUTS"]) + 1
        ind = 0
        while ind < ctr:
            signed = rcrypt.sign_message(prev_keys[0], prev_keys[1])
            ScriptSig = []
            ScriptSig.append(signed[0])
            ScriptSig.append(prev_keys[1])

            tx["vin"].append({
                "txid": rcrypt.make_uuid(),
                "vout_index": ctr,
                "ScriptSig": ScriptSig
            })
            ind += 1

    # Build Vout
    tx["vout"] = []

    ctr = secrets.randbelow(hconfig.conf["MAX_OUTPUTS"]) + 1
    ind = 0
    while ind < ctr:

        ScriptPubKey = []
        ScriptPubKey.append("DUP")
        ScriptPubKey.append("HASH-160")
        ScriptPubKey.append(keys[1])
        ScriptPubKey.append("EQ_VERIFY")
        ScriptPubKey.append("CHECK-SIG")

        tx["vout"] = {
            "value": secrets.randbelow(10000000) + 1000000,  # helium cents
            "ScriptPubKey": ScriptPubKey
        }
        ind += 1

    return tx
Пример #4
0
def make_synthetic_vin(prev_txid, prev_tx_vout_index):
    """
    make a vin object, receives a previous transaction id 
    and a index into the vout list
    returns the vin elemment
    """
    vin = {}
    vin['txid'] = prev_txid
    vin['vout_index'] = prev_tx_vout_index
    vin['ScriptSig'] = []
    vin['ScriptSig'].append(rcrypt.sign_message(prev_tx_keys[0][0], prev_tx_keys[0][1]))
    vin['ScriptSig'].append(prev_tx_keys[0][1])                                        
    return vin
def test_unlock_bad_signature(monkeypatch):
    """ 
    test unlocking a transaction with a bad signature
    """
    global prev_tx_keys

    prev_tx_keys.clear()
    txn1 = make_synthetic_previous_transaction(4)
    txn2 = make_synthetic_transaction(2)

    # make a transaction fragment where the first vin element
    # of txn2 consumes the value of the first vout element of txn1

    # synthetic consuming vin element in tx2
    vin = {}
    vin['txid'] = txn1["transactionid"]
    vin['vout_index'] = 0
    vin['ScriptSig'] = {}

    # use wrong private key to sign 
    key_pair = rcrypt.make_ecc_keys()

    signature = rcrypt.sign_message(key_pair[0], prev_tx_keys[1][1])
    pubkey = prev_tx_keys[1][1]  
    sig = []
    sig.append(signature)
    sig.append(pubkey + "corrupted")
    vin['ScriptSig'] = sig
                                        
    # public key hash in txn2
    ripemd_hash = rcrypt.make_RIPEMD160_hash(rcrypt.make_SHA256_hash(prev_tx_keys[1][1])) 

    fragment = {
        "value": 210,
        "pkhash": ripemd_hash,
        "spent": False,
        "tx_chain": txn2["transactionid"] + "_" + "0",
        "checksum":   rcrypt.make_SHA256_hash(txn1["transactionid"])
    }
    
    assert tx.unlock_transaction_fragment(vin, fragment) == False
def make_random_transaction(blockno, is_coinbase):

    txn = {}
    txn["version"] = "1"
    txn["transactionid"] = rcrypt.make_uuid()
    if is_coinbase == True: txn["locktime"] = hconfig.conf["COINBASE_LOCKTIME"]
    else: txn["locktime"] = 0

    # the public-private key pair for this transaction
    transaction_keys = rcrypt.make_ecc_keys()

    # previous transaction fragments spent by this transaction
    total_spendable = 0

    #######################
    # Build the vin array
    #######################
    txn["vin"] = []

    # genesis block transactions have no prior inputs.
    # coinbase transactions do not have any inputs
    if (blockno > 0) and (is_coinbase != True):
        max_inputs = secrets.randbelow(hconfig.conf["MAX_INPUTS"])
        if max_inputs == 0: max_inputs = hconfig.conf["MAX_INPUTS"] - 1

        # get some random previous unspent transaction
        # fragments to spend
        ind = 0
        ctr = 0

        while ind < max_inputs:
            # get a random unspent fragment from a previous block
            index = secrets.randbelow(len(unspent_fragments))
            frag_dict = unspent_fragments[index]
            key = [*frag_dict.keys()][0]
            val = [*frag_dict.values()][0]
            if val["blockno"] == blockno:
                ctr += 1
                if ctr == 10000:
                    print("failed to get random unspent fragment")
                    return False
                continue

            unspent_fragments.pop(index)

            total_spendable += val["value"]
            tmp = hchaindb.get_transaction(key)
            if tmp == False:
                print("cannot get fragment from chainstate: " + key)

            assert tmp != False
            assert tmp["spent"] == False
            assert tmp["value"] > 0

            # create a random vin element
            key_array = key.split("_")

            signed = rcrypt.sign_message(val["privkey"], val["pubkey"])
            ScriptSig = []
            ScriptSig.append(signed)
            ScriptSig.append(val["pubkey"])

            txn["vin"].append({
                "txid": key_array[0],
                "vout_index": int(key_array[1]),
                "ScriptSig": ScriptSig
            })

            ctr = 0
            ind += 1

    #####################
    # Build Vout list
    #####################
    txn["vout"] = []

    # genesis block
    if blockno == 0:
        total_spendable = secrets.randbelow(10_000_000) + 50_000

    # we need at least one transaction output for non-coinbase
    # transactions
    if is_coinbase == True: max_outputs = hconfig.conf["MAX_OUTPUTS"]
    else:
        max_outputs = secrets.randbelow(hconfig.conf["MAX_OUTPUTS"])
        if max_outputs <= 1: max_outputs = 2

    ind = 0

    while ind < max_outputs:
        tmp = rcrypt.make_SHA256_hash(transaction_keys[1])
        tmp = rcrypt.make_RIPEMD160_hash(tmp)

        ScriptPubKey = []
        ScriptPubKey.append("<DUP>")
        ScriptPubKey.append("<HASH-160>")
        ScriptPubKey.append(tmp)
        ScriptPubKey.append("<EQ-VERIFY>")
        ScriptPubKey.append("<CHECK-SIG>")

        if is_coinbase == True:
            value = hmining.mining_reward(blockno)
        else:
            amt = int(total_spendable / max_outputs)
            value = secrets.randbelow(amt)  # helium cents
            if value == 0:
                value = int(amt / 10)
            total_spendable -= value
            assert value > 0
            assert total_spendable >= 0

        txn["vout"].append({"value": value, "ScriptPubKey": ScriptPubKey})

        # save the transaction fragment
        fragid = txn["transactionid"] + "_" + str(ind)
        fragment = {}
        fragment[fragid] = {
            "value": value,
            "privkey": transaction_keys[0],
            "pubkey": transaction_keys[1],
            "blockno": blockno
        }
        unspent_fragments.append(fragment)
        #print("added to unspent fragments: " + fragid)

        if total_spendable <= 0: break
        ind += 1

    return txn