transaction_type proto_to_transaction(
    const proto::Transaction& proto_tx)
{
    transaction_type result_tx;
    result_tx.version = proto_tx.version();
    result_tx.locktime = proto_tx.locktime();
    for (size_t i = 0; i < proto_tx.inputs_size(); ++i)
    {
        const proto::Transaction::Input& proto_input = proto_tx.inputs(i);
        transaction_input_type tx_input;
        const std::string& prev_out_hash = proto_input.previous_output_hash();
        std::copy(prev_out_hash.begin(), prev_out_hash.end(),
            tx_input.previous_output.hash.begin());
        tx_input.previous_output.index = proto_input.previous_output_index();
        const data_chunk& raw_script = read_raw_script(proto_input);
        if (previous_output_is_null(tx_input.previous_output))
            tx_input.input_script = coinbase_script(raw_script);
        else
            tx_input.input_script = parse_script(raw_script);
        tx_input.sequence = proto_input.sequence();
        result_tx.inputs.push_back(tx_input);
    }
    for (size_t i = 0; i < proto_tx.outputs_size(); ++i)
    {
        const proto::Transaction::Output& proto_output = proto_tx.outputs(i);
        transaction_output_type tx_output;
        tx_output.value = proto_output.value();
        tx_output.output_script = parse_script(read_raw_script(proto_output));
        result_tx.outputs.push_back(tx_output);
    }
    return result_tx;
}
message::transaction read_transaction(
    deserializer& deserial, message::transaction& packet)
{
    packet.version = deserial.read_4_bytes();
    uint64_t tx_in_count = deserial.read_variable_uint();
    for (size_t tx_in_i = 0; tx_in_i < tx_in_count; ++tx_in_i)
    {
        message::transaction_input input;
        input.previous_output.hash = deserial.read_hash();
        input.previous_output.index = deserial.read_4_bytes();
        if (previous_output_is_null(input.previous_output))
            input.input_script = coinbase_script(read_raw_script(deserial));
        else
            input.input_script = read_script(deserial);
        input.sequence = deserial.read_4_bytes();
        packet.inputs.push_back(input);
    }
    uint64_t tx_out_count = deserial.read_variable_uint();
    for (size_t tx_out_i = 0; tx_out_i < tx_out_count; ++tx_out_i)
    {
        message::transaction_output output;
        output.value = deserial.read_8_bytes();
        output.output_script = read_script(deserial);
        packet.outputs.push_back(output);
    }
    packet.locktime = deserial.read_4_bytes();
    return packet;
}
script read_script(deserializer& deserial)
{
    data_chunk raw_script = read_raw_script(deserial);
#ifndef BITCOIN_DISABLE_ASSERTS
    std::string assert_msg = pretty_hex(raw_script);
#endif
    BITCOIN_ASSERT_MSG(
        raw_script == save_script(parse_script(raw_script)),
        assert_msg.c_str());
    // Eventually plan to move parse_script to inside here
    return parse_script(raw_script);
}