You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: transaction.rs
    path of file: ./repos/saito-rust/src
    
    the code of the file until where you have to start completion: use std::convert::TryInto;

use crate::{
    blockchain::UtxoSet,
    crypto::{
        generate_random_bytes, hash, sign, verify, SaitoHash, SaitoPrivateKey, SaitoPublicKey,
        SaitoSignature, SaitoUTXOSetKey,
    },
    hop::{Hop, HOP_SIZE},
    slip::{Slip, SlipType, SLIP_SIZE},
    staking::Staking,
    wallet::Wallet,
};
use ahash::AHashMap;
use bigint::uint::U256;
use log::{error, info};
use macros::TryFromByte;
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;

use rayon::prelude::*;
use std::sync::Arc;
use tokio::sync::RwLock;

pub const TRANSACTION_SIZE: usize = 89;

/// TransactionType is a human-readable indicator of the type of
/// transaction such as a normal user-initiated transaction, a
/// golden ticket transaction, a VIP-transaction or a rebroadcast
/// transaction created by a block creator, etc.
#[derive(Serialize, Deserialize, Debug, Copy, PartialEq, Clone, TryFromByte)]
pub enum TransactionType {
    Normal,
    Fee,
    GoldenTicket,
    ATR,
    Vip,
    StakerDeposit,
    StakerWithdrawal,
    Issuance,
    SPV,
}

#[serde_with::serde_as]
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct Transaction {
    // the bulk of the consensus transaction data
    timestamp: u64,
    pub inputs: Vec<Slip>,
    pub outputs: Vec<Slip>,
    #[serde(with = "serde_bytes")]
    message: Vec<u8>,
    transaction_type: TransactionType,
    #[serde_as(as = "[_; 64]")]
    signature: SaitoSignature,
    path: Vec<Hop>,

    // hash used for merkle_root (does not include signature), and slip uuid
    hash_for_signature: Option<SaitoHash>,

    pub total_in: u64,
    pub total_out: u64,
    pub total_fees: u64,
    pub cumulative_fees: u64,

    pub routing_work_for_me: u64,
    pub routing_work_for_creator: u64,
}

impl Transaction {
    #[allow(clippy::new_without_default)]
    pub fn new() -> Self {
        Self {
            timestamp: 0,
            inputs: vec![],
            outputs: vec![],
            message: vec![123, 125], // to match with JS {}
            transaction_type: TransactionTy
    
    pub fn get_winning_routing_node(&self, random_hash: SaitoHash) -> SaitoPublicKey {
        //
        // if there are no routing paths, we return the sender of
        // the payment, as they're got all of the routing work by
        // definition. this is the edge-case where sending a tx
        // can make you money.
        //
        if self.path.is_empty() {
            if !self.inputs.is_empty() {
                return self.inputs[0].get_publickey();
            } else {
                return [0; 33];
            }
        }

        //
        // no winning transaction should have no fees unless the
        // entire block has no fees, in which case we have a block
        // without any fee-paying transactions.
        //
        // burn these fees for the sake of safety.
        //
        if self.get_total_fees() == 0 {
            return [0; 33];
        }

        //
        // if we have a routing path, we calculate the total amount
        // of routing work that it is possible for this transaction
        // to contain (2x the fee).
        //
        let mut aggregate_routing_work: u64 = self.get_total_fees();
        let mut routing_work_this_hop: u64 = aggregate_routing_work;
        let mut work_by_hop: Vec<u64> = vec![];
        work_by_hop.push(aggregate_routing_work);

        for _i in 1..self.path.len() {
            let new_routing_work_this_hop: u64 = routing_work_this_hop / 2;
            aggregate_routing_work += new_routing_work_this_hop;
            routing_work_this_hop = new_routing_work_this_hop;
            work_by_hop.push(aggregate_routing_work);
        }

        //
        // find winning routing node
        //
        let x = U256::from_big_endian(&random_hash);
        let z = U256::from_big_endian(&aggregate_routing_work.to_be_bytes());
        let (zy, _bolres) = x.overflowing_rem(z);
        let winning_routing_work_in_nolan = zy.low_u64();

        for i in 0..work_by_hop.len() {
            if winning_routing_work_in_nolan <= work_by_hop[i] {
                return self.path[i].get_to();
            }
        }

        //
        // we should never reach this
        //
        [0; 33]
    }