Example #1
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
Example #2
0
def make_miner_keys():
    """
    makes a public-private key pair that the miner will use to receive
    the mining reward and the transaction fee for each transaction.
    This function writes the  keys to a file and returns hash: 
    RIPEMD160(SHA256(public key))
    """

    try:
        keys = rcrypt.make_ecc_keys()
        privkey = keys[0]
        pubkey = keys[1]

        pkhash = rcrypt.make_SHA256_hash(pubkey)
        mdhash = rcrypt.make_RIPEMD160_hash(pkhash)

        # write the keys to file with the private key as a hexadecimal string
        f = open('coinbase_keys.txt', 'a')
        f.write(privkey)
        f.write('\n')  # newline
        f.write(pubkey)
        f.write('\n')
        f.close()

    except Exception as err:
        logging.debug('make_miner_keys: exception: ' + str(err))

    return mdhash
Example #3
0
def make_keys():
    """ 
    makes a private-public key pair for the synthetic
    previous transaction
    """
    prev_tx_keys.clear()
    key_pair = rcrypt.make_ecc_keys()
    prev_tx_keys.append([key_pair[0],key_pair[1]])
    return
def test_scriptsig_length_error():
    """
    test if the ScriptSig list has invalid length
    """
    txn = make_synthetic_transaction(2)
    indices = randomize_list(txn['vin'])
    keys = rcrypt.make_ecc_keys()

    for ctr in list(range(len(indices))):
        txn["vin"][indices[ctr]]['ScriptSig'].append(keys[1])
        assert tx.validate_vin(txn['vin'][indices[ctr]]) == False
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
def test_make_ecc_keys():
    """
    test ECC private-public key pair
    """
    ecc_keys = rcrypt.make_ecc_keys()
    assert ecc_keys[0].find("BEGIN PRIVATE KEY") >= 0
    assert ecc_keys[0].find("END PRIVATE KEY") >= 0
    assert ecc_keys[0].find("END PRIVATE KEY") > ecc_keys[0].find(
        "BEGIN PRIVATE KEY")
    assert ecc_keys[1].find("BEGIN PUBLIC KEY") >= 0
    assert ecc_keys[1].find("END PUBLIC KEY") >= 0
    assert ecc_keys[1].find("END PUBLIC KEY") > ecc_keys[1].find(
        "BEGIN PUBLIC KEY")
 def make_synthetic_vout():
     """
     make a synthetic vout object.
     returns a vout dictionary item
     """
     key_pair = rcrypt.make_ecc_keys()
     global prev_tx_keys
     prev_tx_keys.append([key_pair[0],key_pair[1]])
     vout = {}
     vout['value'] = secrets.randbelow(1000000) + 1000  # helium cents
     
     tmp = []
     tmp.append('<DUP>')
     tmp.append('<HASH-160>')
     tmp.append(key_pair[1])
     tmp.append('<EQ-VERIFY>')
     tmp.append('<CHECK-SIG>')
     vout['ScriptPubKey'] = tmp
     return vout
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_synthetic_transaction(block):
    """
    makes a synthetic transaction with randomized values
    """

    transaction = {}
    transaction['version'] = hconfig.conf["VERSION_NO"]
    transaction['transactionid'] = rcrypt.make_uuid()
    transaction['locktime'] = 0
    transaction['vin'] = []
    transaction['vout'] = []

    # make public-private key pair for the transaction
    pair = rcrypt.make_ecc_keys()
    tx_keys[transaction["transactionid"]] = pair

    # make vin list
    # genesis block does not have inputs
    if block["height"] > 0:
        num_inputs = secrets.randbelow(3) + 1
        for ctr in range(num_inputs):
            trx = make_synthetic_vin(transaction, ctr)
            if trx == False: break
            transaction["vin"].append(trx)

    # make vout list
    num_outputs = secrets.randbelow(5) + 1
    ctr = 0
    for ctr in range(num_outputs):
        vout = make_synthetic_vout(block, transaction, ctr, pair[1])
        if vout != False: transaction["vout"].append(vout)

    block["tx"].append(transaction)
    hchaindb.transaction_update(transaction)

    return transaction
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
Example #11
0
def create_keys():
    key_pair = rcrypt.make_ecc_keys()
    wallet_state["keys"].append(key_pair)