\chapter{Methodology}
\section{System Architecture}
\label{sec:system_architecture}

To build our proposed system, we designed a multi-layer architecture, which is a common and very effective pattern in modern software engineering. This approach is sometimes called a ``three-tier architecture`` as it logically separates the application's main functions. For our project, this means the user interface (frontend), the business logic (backend), and the data storage (database and blockchain) are all independent components. This separation of concerns is very important because it make the system much easier to develop, test, and maintain.

A general overview of this architecture is shown in Figure \ref{fig:system_arch}. The following sections will describe each of these layers in more detail.

\begin{figure}[H]
\begin{center}
\includegraphics[width=12cm]{Figures/system_architecture.png} 
\caption{The high-level system architecture, showing the connection between the user, backend, database, and blockchain.}
\label{fig:system_arch}
\end{center}
\end{figure}

The source code for the implementation is available at:
\begin{itemize}
    \item \textbf{Backend Repository:} \url{https://github.com/amirhossein-shekari/backend-train-inventory}
    \item \textbf{Frontend Repository:} \url{https://github.com/amirhossein-shekari/frontend-train-inventory}
\end{itemize}

\subsection{Architectural Design Rationale}
\label{sec:design_rationale}

Before building, we had to make a key decision. A ``pure`` decentralized application (DApp), where all logic and data lives on-chain, has many problems for an enterprise system. It can be very slow, as every action must be a transaction. It is also very expensive, as storing data on the blockchain costs 'gas' (money). This is not practical for a complex system like a railway inventory which might generate thousands of data points.

Therefore, we chose a \textbf{hybrid architecture}. This design is the foundation of our contribution. It combines the best parts of a traditional web application (speed, low cost) with the best parts of blockchain (security, immutability). This hybrid model is a common pattern in enterprise blockchain applications, as it solves the trade-offs between cost, speed, and trust \cite{hybrid_on_off_chain}.

The core idea is to separate two types of data:
\begin{enumerate}
    \item \textbf{Critical Asset Data:} Information about the trains, wagons, their relationships, and their maintenance history. This data needs to be secure and auditable. This data is perfect for the blockchain.
    \item \textbf{Application Data:} Information like user accounts, hashed passwords, and session tokens. This data is needed for the application to work, but it does not need tobe immutable or decentralized.
\end{enumerate}

This hybrid design gives us great benefits. We get the speed and low cost of a traditional database for everyday tasks like user login. But we get the high security, immutability, and transparency of the blockchain for the most important data: the asset registry and maintenance logs.

\subsection{Presentation Layer (Frontend)}
\label{sec:frontend}

This is the user interface (UI) that the railway staff will use. It is the ``face`` of our application. We developed this as a web-based application built using the React library, a popular and modern choice for building user interfaces.

\begin{itemize}
    \item \textbf{Technology Choice:} We chose React because it allows us to build a \textbf{Single-Page Application (SPA)}. This means the user loads the application once, and then all navigation (like moving from the 'Trains' page to the 'Wagons' page) is very fast and smooth, without reloading the whole web page. React's component-based model also allowed us to create reusable UI parts, for example a single 'Asset Form' component could be used for both creating a new train and for editing an existing train.
    
    \item \textbf{Functionality:} This layer provides all the tools the user interacts with. This includes:
    \begin{itemize}
        \item A main \textbf{Dashboard} to show summary statistics (like how many assets are operational).
        \item \textbf{Data Grids} and tables for listing all trains, wagons, and equipment.
        \item \textbf{Interactive Forms} and modal pop-ups for creating new assets or updating existing ones (e.g., changing a wagon's mileage).
        \item A secure \textbf{Login Page} to handle user authentication.
    \end{itemize}
    
    \item \textbf{Data Handling:} The frontend does not have any direct business logic. Its main job is to show data from the backend and send the user's input back to the backend. We used a modern data-fetching library, React Query, to manage all API calls. This library is very smart, it handles caching of data (to make the app feel faster) and automatically updates the data in the background.
\end{itemize}

\subsection{Backend Logic Layer (API Middleware)}
\label{sec:backend}

This layer is the central 'bridge' and the 'brain' of our system. It connects the frontend to our data layers. In academic terms, this is a \textbf{blockchain middleware} layer \cite{blockchain_middleware}. Its role is to abstract the complexity of the blockchain from the end-user. The frontend does not know how to speak to the blockchain; it only speaks to this backend API.

We built this layer as a REST API using the \textbf{FastAPI} framework in Python. We choose this technology because it is very high performance, and it automatically creates interactive API documentation (using OpenAPI), which was very helpful for our development and testing process.

The backend is responsible for several critical tasks:

\begin{enumerate}
    \item \textbf{Request Handling and Validation:} It receives all network requests from the frontend. For example, when the user submits a form to create a new train, the frontend sends a request to the \texttt{POST /v1/trains} endpoint. The backend validates this data to make sure all required fields (like 'name') are present.
    
    \item \textbf{Authentication and Authorization:} This layer handles all user security. When a user tries to login, the API checks their username and password against the data stored in our SQLite database. It creates a secure \textbf{JSON Web Token (JWT)} and sends it back to the user. For all other API calls, the frontend must send this token. The backend will validate the token on every request to prove who the user is. This is a key part of our hybrid design: user authentication is handled off-chain, which is faster and more secure, as user passwords should never be stored on a public blockchain \cite{dapp_access_control}.
    
    \item \textbf{Data Orchestration:} This is the most important job. The backend is the 'orchestrator' that decides where data should go. When a user creates a new user account, the backend hashes the password and saves it to the local SQLite database. When a user creates a new maintenance record, the backend creates and sends a transaction to the blockchain smart contract. The backend is the *only* component that holds the private keys and node connections (e.g., to Alchemy) necessary to write to the blockchain.
\end{enumerate}

\subsection{Data Layers (A Hybrid Approach)}
\label{sec:data_layers}

This is the most critical part of our thesis, the foundation of the whole system. As mentioned in the design rationale, we use a hybrid data model with two distinct storage layers. This approach is recognized in research as a practical solution for balancing the trade-offs of performance, cost, and data integrity \cite{dapp_architecture}.

\subsubsection{On-Chain Data: The Blockchain Ledger}
The smart contract is our decentralized data layer. This is the single source of truth for all \textit{critical asset data}. We decided that any data related to the asset's identity, its hierarchical relationship, and its maintenance status must be on-chain.

This gives us the key benefits of blockchain, which are central to our thesis. For a high-stakes industry like railway transport, an auditable and immutable record of maintenance is essential for safety and regulation. Research has shown that blockchain is an effective tool for this, creating a transparent and verifiable management system \cite{railway_maintenance}.

Specifically, we store the following data on-chain:
\begin{itemize}
    \item The full list of \textbf{Trains}, \textbf{Wagons}, and \textbf{Equipment}.
    \item The \textbf{hierarchical links} between them (e.g., mapping which wagons belong to which train).
    \item The critical \textbf{maintenance status} for each piece of equipment (e.g., \texttt{isOperational} and \texttt{lastMaintenance}).
    \item Key metadata like \texttt{mileage}, \texttt{manufacturer}, and \texttt{originCountry}.
\end{itemize}
This section only describes *what* is stored; the next section (3.2) will describe *how* it is stored and managed inside the contract.

\subsubsection{Off-Chain Data: The Local Application Database}
At the same time, we use a traditional, centralized database. Our backend uses SQLAlchemy, an 'Object Relational Mapper' (ORM), to connect to a simple \textbf{SQLite} database file.

We use this database for storing \textit{non-critical and centralized application data}. This includes:
\begin{itemize}
    \item User accounts (username, hashed passwords).
    \item User roles (e.g., 'admin', 'mechanic'), which we can use to control permissions.
    \item Authentication tokens for managing user sessions.
\end{itemize}

This information must not be on the blockchain. It is a very bad and insecure practice to store user passwords or other personally identifiable information (PII) on a public ledger. This data is also not part of the 'asset history' which we want to make immutable. This choice makes our application more secure, faster (logging in is a simple database check, not a slow blockchain transaction), and much cheaper.

\subsection{Example Workflow: The Maintenance Process}
\label{sec:data_flow_summary}

To make the full architecture clear, let's follow the data flow for one complete action: ``A mechanic performs maintenance on a piece of equipment.``

\begin{enumerate}
    \item \textbf{Login:} The mechanic opens the web application and enters their username and password. The \textbf{Frontend} sends this to the \textbf{Backend}. The Backend hashes the password and compares it to the hash in the \textbf{SQLite Database}. The check is successful. The Backend creates a JWT token and sends it back to the Frontend.
    
    \item \textbf{View Data:} The mechanic navigates to the 'Equipment' page. The \textbf{Frontend} sends a request to the Backend (with the JWT token) to get all equipment. The \textbf{Backend} checks the token (using SQLite) to see if the user is authenticated. The token is valid.
    
    \item \textbf{Read from Blockchain:} The \textbf{Backend} then calls a 'view' (read-only) function on the \textbf{Blockchain Smart Contract} to get the list of all active equipment. This read operation is free and does not cost gas.
    
    \item \textbf{Display Data:} The \textbf{Blockchain} returns the data to the \textbf{Backend}, which then formats it as JSON and sends it to the \textbf{Frontend}. The mechanic sees the full list of equipment.
    
    \item \textbf{Perform Maintenance:} The mechanic finds a broken part (its status is \texttt{isOperational: false}). They fix it, and then go to the application to update its status. They fill out the form and click ``Submit``.
    
    \item \textbf{Write to Blockchain:} The \textbf{Frontend} sends this new data to the \textbf{Backend}. The Backend validates the JWT token and the new data.
    
    \item \textbf{Backend Orchestration:} This is the key step. The \textbf{Backend} creates and signs a new \textit{transaction} to call the \texttt{updateEquipment} function on the \textbf{Blockchain Smart Contract}. This is a 'write' operation, so it will cost a small amount of gas to execute.
    
    \item \textbf{Confirmation:} The blockchain network confirms the transaction. The new data (the updated status and maintenance date) is now permanently recorded in the ledger.
    
    \item \textbf{Update UI:} The \textbf{Backend} receives the confirmation and sends a ``Success`` message to the \textbf{Frontend}. The mechanic's screen updates to show the new, 'operational' status for the part.
\end{enumerate}

This flow shows how all the layers work together perfectly. We use the fast off-chain database for centralized tasks like login, and the secure, immutable on-chain ledger for the important maintenance record.

% new sub chapter explain blockchain

\section{The Blockchain Core: Railway Asset Registry}
\label{sec:blockchain_core}

This section details the technical implementation of the on-chain component, which is the heart of our decentralized system. As we discussed in the system architecture, this component is a smart contract that acts as a secure, immutable, and auditable ledger for all railway assets. It is designed to be the single source of truth for asset identity, relationships, and maintenance status.

Our design goals for this smart contract were:
\begin{itemize}
    \item \textbf{Data Integrity:} Ensuring that data is correct and that relationships (like a wagon belonging to a train) are always valid.
    \item \textbf{Auditable History:} Making it impossible to delete or modify maintenance records, while still allowing for assets to be 'retired' from active service.
    \item \textbf{Query Efficiency:} Allowing the backend to retrieve data for the application (like ``all wagons on train 5``) quickly and efficiently.
    \item \textbf{Gas Optimization:} Making all operations, especially writing data, as cheap as possible to ensure the system is economically viable to use.
\end{itemize}

To achieve these goals, we used the Solidity programming language, compiling with version \texttt{\^0.8.0}. This version is important, as it includes built-in arithmetic safety checks, which protects our contract from overflow and underflow bugs without needing external libraries.

\subsection{Development, and Deployment Lifecycle}
\label{sec:dev_lifecycle}

A complex smart contract is not a simple script. It requires a professional development lifecycle, which includes a local development environment, a strong testing framework, and a clear deployment pipeline. This is critical because smart contracts are immutable, meaning a bug deployed to the main network can be impossible to fix and can lead to major problems.

\subsubsection{Development Environment}
For building this complex contract, we need a professional development environment. We chose \textbf{Hardhat}, which is a very popular and powerful framework for Ethereum development \cite{hardhat}. Hardhat is important for our project because it provides many tools that make development easier and more reliable.

The most important feature for us was the \textbf{Hardhat Network}. This is a local Ethereum network that runs on our own computer. It starts up instantly and gives us 'fake' ETH to pay for transactions. This allowed us to compile and test our contract hundreds of times very quickly, without needing to connect to a real, slow, and expensive public network. We also wrote scripts to deploy our contract to this local network, so we could connect our backend and frontend to it for full-stack testing.

\subsubsection{Deployment to a Test Network}
After all local tests passed, we deployed our contract to a public \textbf{test network (testnet)}. We chose the \textbf{Sepolia testnet}. Sepolia is the modern, recommended testnet for Ethereum application development, as it is maintained by the core developers.

To deploy to Sepolia, we cannot connect directly. We must use a \textbf{node provider} service. For this project, we used \textbf{Alchemy} \cite{alchemy}. Alchemy runs a high-availability Ethereum node for us, and gives us a special URL (an RPC endpoint) that our deployment scripts can use. We used Hardhat's scripting tools to write a deployment script that reads our compiled contract, connects to Alchemy, and securely sends the 'create contract' transaction to the Sepolia network using our private key. This process gave us a real contract address on a public network, which our backend could then be configured to use. This is the same process that would be used for a final 'mainnet' (production) deployment.

\subsection{On-Chain Data Structures}
\label{sec:data_structures}

The first step in designing the contract was to define the data models. We used Solidity's \texttt{struct} type to create custom data templates for our three main asset types.

\begin{itemize}
    \item \textbf{\texttt{Train} struct:} This is the highest-level asset. It contains basic identity fields like \texttt{name}, \texttt{manufacturer}, and \texttt{originCountry}. Critically, it also includes a \texttt{mileage} field. This is a \texttt{uint32} (32-bit unsigned integer) that the backend must update. This field is the foundation for any future predictive maintenance logic, as the system can check this value to schedule service.
    
    \item \textbf{\texttt{Wagon} struct:} This is the intermediate asset, representing a single car. It contains its own metadata, like \texttt{wagonType} (e.g., ``Passenger`` or ``Cargo``) and \texttt{purchaseDate}. Its most important field is \texttt{trainId}. This is the 'foreign key' that creates the hierarchical link, proving which train this wagon is part of.
    
    \item \textbf{\texttt{Equipment} struct:} This is the most granular asset, representing a component inside a wagon (e.g., a braking system, HVAC unit, or door assembly). This struct is the linchpin of our thesis's ``maintenance`` goal. It contains two vital fields:
    \begin{enumerate}
        \item \texttt{isOperational}: A boolean (\texttt{true/false}) value that gives an immediate, real-time status of the part.
        \item \texttt{lastMaintenance}: A timestamp (stored as a \texttt{uint32}) that is updated by a mechanic. The combination of these two fields provides a complete, auditable maintenance log.
    \end{enumerate}
    This struct also contains a \texttt{wagonId} to link it to its parent wagon.
\end{itemize}

A key part of our optimization strategy was the choice of data types. For all identifiers (\texttt{id}) and timestamps, we chose \texttt{uint32} instead of the default \texttt{uint256}. This is a significant \textbf{gas optimization}. A \texttt{uint32} uses 8 times less storage on the blockchain than a \texttt{uint256}. Because writing to storage is the most expensive operation in Ethereum, this choice makes every transaction that creates or updates an asset cheaper. This is a common best practice in gas optimization \cite{gasopt_practices}. A 32-bit integer can store a number up to 4.29 billion, which is more than enough for the number of assets in a railway system, and it can represent Unix timestamps until the year 2106.

\subsection{Storage, Relationships, and Indexing}
\label{sec:storage_mappings}

After
defining our data \textit{shape} (the structs), we needed to design the data \textit{storage}. In Solidity, the primary way to store data is with \texttt{mapping} variables. A mapping is like a giant hash map or dictionary, where you can store a value at a specific key. This is the only way to efficiently retrieve a single piece of data without looping through an entire array.

We designed three different types of mappings to manage our data, relationships, and search indexes.

\subsubsection{Data Storage Mappings}
These are our primary ``database tables``. They link a unique ID to the full struct data for that asset.
\begin{verbatim}
    mapping(uint32 => Train) private trains;
    mapping(uint32 => Wagon) private wagons;
    mapping(uint32 => Equipment) private equipment;
\end{verbatim}
This allows us to instantly find any asset (e.g., \texttt{wagons[101]}) just by knowing its ID. We marked these as \texttt{private} so that other contracts cannot access them directly; they must use our designated functions.

\subsubsection{Hierarchical Relationship Mappings}
This is how we solved the problem of linking assets together. We created mappings that link a parent's ID to a \textit{list} of its children's IDs.
\begin{verbatim}
    mapping(uint32 => EnumerableSet.UintSet) private _wagonsByTrain;
    mapping(uint32 => EnumerableSet.UintSet) private _equipmentByWagon;
\end{verbatim}
Here, we made another key design choice. We did not use a simple array (\texttt{uint32[]}) for the list. Instead, we imported the \textbf{\texttt{EnumerableSet}} library from OpenZeppelin \cite{openzeppelin_set}. OpenZeppelin is a trusted provider of secure smart contracts. An \texttt{EnumerableSet} is a special data structure that acts like a list, but has several advantages:
\begin{itemize}
    \item \textbf{Add/Remove:} Adding or removing an ID is very fast and has a constant gas cost. In a large array, removing an item can be very expensive.
    \item \textbf{Contains:} The set can instantly check if an ID is already in the list (\texttt{contains(id)}). This is impossible in an array without an expensive loop.
\end{itemize}
This set is the key to our tracking logic. When we add a new wagon, we also add its ID to the \texttt{\_wagonsByTrain} set of its parent train.

\subsubsection{Search Index Mappings}
A major challenge in Solidity is that mappings are not searchable by their \textit{value}. For example, we cannot ask the \texttt{wagons} mapping to ``find all wagons where \texttt{wagonType} is 'Cargo'``.

To solve this, we implemented our own \textbf{inverted indexes}. This is a common software engineering design pattern that we applied to Solidity \cite{contract_patterns}. We created special mappings where the \textit{key} is the value we want to search for, and the \textit{value} is a set of IDs.
\begin{verbatim}
    mapping(bytes32 => EnumerableSet.UintSet) private _wagonsByName;
    mapping(bytes32 => EnumerableSet.UintSet) private _wagonsByType;
\end{verbatim}
The key is \texttt{bytes32}, not a \texttt{string}. This is because strings are complex and expensive to use as mapping keys. When a new wagon is added, we take its name (e.g., ``Wagon 12A``), convert it to bytes, and then compute its \texttt{keccak256} hash. This hash is a unique 32-byte key. We then add the wagon's ID to the \texttt{EnumerableSet} stored at that hash in the \texttt{\_wagonsByName} mapping.

This is a powerful technique. Now, if the user wants to search for all wagons named ``Wagon 12A``, the backend just computes the same hash and queries our mapping. It instantly gets the set of all IDs for wagons with that name.

\subsection{Asset Lifecycle Management Functions}
\label{sec:lifecycle_functions}

These are the state-changing functions that our backend API calls to create, update, and delete assets. These functions are the core of the business logic and are directly related to the goals of using blockchain for asset management. Studies have shown that blockchain can significantly improve the security and reliability of maintenance data \cite{railway_maintenance_cost}, and these functions are how we implement that promise.

\subsubsection{Asset Creation}
We created \texttt{addTrain}, \texttt{addWagon}, and \texttt{addEquipment} functions. The logic for adding a child asset (like a wagon) is more complex than adding a parent (like a train). When \texttt{addWagon} is called:
\begin{enumerate}
    \item \textbf{Parent Check:} The function first checks if the parent \texttt{trainId} exists and is an active train. If not, it reverts the transaction. This is a critical data integrity check to prevent ``orphan`` assets.
    \item \textbf{ID Generation:} It increments a private counter (\texttt{\_wagonCount}) to get a new, unique ID.
    \item \textbf{Data Storage:} It creates the new \texttt{Wagon} struct and saves it in the main \texttt{wagons} mapping.
    \item \textbf{Index Update:} This is the crucial part. The function updates all our other mappings. It adds the new ID to the \texttt{\_activeWagons} set, the \texttt{\_wagonsByTrain} set of its parent, and the search indexes.
    \item \textbf{Event Emission:} Finally, it emits an event to notify the backend that a new wagon was created.
\end{enumerate}

\subsubsection{Asset Updating}
The update functions are the most complex in the entire contract, as they must carefully manage all the indexes. The \texttt{updateWagon} function is the best example. When a user changes a wagon's name and moves it to a new train:
\begin{enumerate}
    \item \textbf{Existence Check:} It checks if the wagon ID exists and is active.
    \item \textbf{Parent Check:} It checks if the \textit{new} parent train ID is also active.
    \item \textbf{Relationship Update:} It removes the wagon ID from the \texttt{\_wagonsByTrain} set of the \textit{old} train and adds it to the set of the \textit{new} train.
    \item \textbf{Search Index Update:} This is the most complex step. It must:
        \begin{itemize}
            \item Get the \textit{old} name, hash it, and \textit{remove} the wagon ID from the \texttt{\_wagonsByName} index.
            \item Get the \textit{new} name, hash it, and \textit{add} the wagon ID to the \texttt{\_wagonsByName} index.
            \item It does the same for the \texttt{wagonType} if it was changed.
        \end{itemize}
    \item \textbf{Data Update:} Only after all indexes are updated, it updates the data in the main \texttt{wagons} struct.
\end{enumerate}

\subsubsection{Asset Deletion Strategy (Soft vs. Hard)}
This is a core part of our ``auditable history`` goal. One of the main benefits of using blockchain for asset tracking is to create an immutable log \cite{railway_monitoring}. Deleting data from a blockchain is permanent and generally a bad idea for an audit trail.

\textbf{Soft Deletion:} We implemented a 'soft delete' pattern. We maintain an \texttt{EnumerableSet} for all active assets (\texttt{\_activeTrains}, \texttt{\_activeWagons}, \texttt{\_activeEquipment}). When the \texttt{deleteWagon} function is called, it does \textit{not} use the \texttt{delete} keyword. Instead, it simply removes the wagon's ID from the \texttt{\_activeWagons} set and from all search/relationship indexes. The original \texttt{Wagon} struct is still in the blockchain storage, forever. It is now ``inactive``. Our query functions are designed to only return ``active`` assets, so this wagon disappears from the application, but its history is preserved for any auditor.

This soft delete is also \textbf{cascading}. When \texttt{deleteTrain} is called, it loops through all wagon IDs in its \texttt{\_wagonsByTrain} set and calls \texttt{\_deleteWagon} on each one. This, in turn, cascades down and soft-deletes all equipment. This prevents ``orphan`` child assets. We also implemented \texttt{undeleteTrain} functions that can restore an asset by re-adding it to the active sets and indexes.

\textbf{Hard Deletion:} We also included \texttt{hardDeleteTrain} functions. These functions use the \texttt{delete} keyword, which completely removes the struct data from storage and provides a small gas refund. These are dangerous functions and should only be exposed to a high-level admin. They are not for normal operation, but are useful for purging data that was created by mistake.

\subsection{Query and Data Retrieval Functions}
\label{sec:query_functions}

These are the \texttt{view} (read-only) functions that our backend calls to get data for the frontend. These functions do not cost any gas to call.

\begin{itemize}
    \item \textbf{Relational Queries:} Functions like \texttt{wagonsOfTrain(trainId)} are simple. They just look up the \texttt{trainId} in the \texttt{\_wagonsByTrain} mapping and return the list of wagon IDs from the \texttt{EnumerableSet}.
    
    \item \textbf{Search Queries:} Functions like \texttt{searchWagonsByName(string calldata name)} are more complex. They first hash the input name to get the \texttt{bytes32} key. Then they query the \texttt{\_wagonsByName} index to get the set of matching IDs.
    
    \item \textbf{The Active Filter:} A key detail is that search queries do not return the set directly. They pass the results to an internal helper function, \texttt{\_filterActive}. This function loops through the IDs from the search index and, for each ID, checks \texttt{\_activeWagons.contains(id)}. It builds a new array containing \textit{only} the IDs that are in the active set. This is the other half of our soft-delete logic. It guarantees that our search results never contain ``deleted`` assets.
    
    \item \textbf{Detail Queries:} We created helper functions like \texttt{getWagonDetail(wagonId)}. This is an aggregation function for the backend. In one call, it returns the \texttt{Wagon} struct itself, the parent \texttt{Train} struct, and the array of all child \texttt{Equipment} IDs. This is very efficient for the backend, as it prevents it from having to make three separate calls to the contract to get all the data for one page.
\end{itemize}

\subsection{Gas, Security, and Opcode Optimization}
\label{sec:gas_security_optimization}

Finally, a smart contract must be efficient. High gas costs can make a system unusable. Academic research has shown that inefficient smart contracts are a major problem, and that many optimizations are possible \cite{gas_analysis_optimization}. We focused on several key optimizations.

\subsubsection{Compiler Opcode Optimization}
A smart contract must be compiled from Solidity into 'opcodes' (operation codes) for the Ethereum Virtual Machine (EVM). We can 'optimize' this process. We enabled the Solidity optimizer with a \textbf{`runs` value of 200}.

This \texttt{runs} value is a setting we give to the compiler. It tells the compiler how many times we expect to \textit{call} each function during the contract's lifetime. A value of 200 is a standard default that finds a good balance between two different costs \cite{solidityoptimizer}:
\begin{enumerate}
    \item \textbf{Deployment Cost:} The one-time cost to put the contract on the blockchain.
    \item \textbf{Runtime Cost:} The cost to call a function, like \texttt{addWagon}, every time.
\end{enumerate}
A low \texttt{runs} value (like 1) makes the deployment cheap but the functions more expensive. A high \texttt{runs} value (like 10,000) makes the deployment very expensive but optimizes the functions to be very cheap. We chose \textbf{200} as a sensible trade-off for our system.

\subsubsection{Custom Errors}
This is a modern Solidity feature for gas optimization. Instead of reverting a transaction with a string, like \texttt{revert(``Parent train is not active``);}, which is very expensive, we define custom errors at the top of the contract.
\begin{verbatim}
    error NotActive(uint8 kind);
    error NotFound(uint8 kind);
    error ParentNotActive(uint8 parent);
\end{verbatim}
When a check fails, we use \texttt{revert ParentNotActive(K\_TRAIN);}. This seems like a small change, but it has a huge impact. Using custom errors instead of strings saves a large amount of gas when we first \textit{deploy} the contract, and also saves gas every time a transaction \textit{fails}. This is a modern best practice \cite{gasopt_practices}.

\subsubsection{Asynchronous Events}
The blockchain is asynchronous. When the backend sends a transaction (like \texttt{addWagon}), it only knows that the transaction was *sent*, not when it was *confirmed*. To solve this, we use an \texttt{event}.
\begin{verbatim}
    event AssetChanged(uint32 indexed id, AssetType indexed assetType);
\end{verbatim}
We emit this event every time an asset is created, updated, or deleted. The \texttt{indexed} keyword allows our backend to easily filter for events (e.g., ``only tell me about changes to \texttt{AssetType.Wagon}``). Our backend server can subscribe to this event. This is much more efficient than ``polling`` (asking the contract ``any changes?`` every 5 seconds). The blockchain *tells* our server immediately when a change happens.


% section for backend implementation (FastAPI, database, blockchain connection)

\section{Application Backend (API Layer)}
\label{sec:backend_api}

If the smart contract is the 'decentralized ledger', then the backend is the 'central brain' of our application. This layer is a \textbf{middleware}, it works as the bridge between the simple frontend application and the very complex blockchain. This layer is responsible for three main jobs: 1) handling user authentication, 2) managing off-chain data (like user accounts), and 3) orchestrating all communication with the smart contract (like sending transactions).

Our choice of a middleware-based architecture is a very important design decision. A 'pure' decentralized application (DApp) would require the user's web browser to talk directly to the blockchain. This has many problems, it is not secure (users must manage their own private keys), it is complex, and it cannot handle centralized logic like user roles. Our backend API solves this. Research on blockchain systems calls this an 'API-centric' or 'middleware' pattern, which is a practical way to build hybrid applications \cite{blockchain_middleware_api}.

\subsection{Technology Choice: Python and FastAPI}
\label{sec:backend_tech}

For our backend technology, we choice to use Python with the \textbf{FastAPI} framework. This was not a random choice. We needed a framework that was very high-performance and modern.

\begin{itemize}
    \item \textbf{Performance:} FastAPI is an 'asynchronous' framework (ASGI). This means it can handle many user requests at the same time without getting stuck. This is important for us, because some requests might be very slow (like waiting for a blockchain transaction to be confirmed). The async design means the server can handle other user requests while it waits.
    
    \item \textbf{Data Validation:} FastAPI is built on a library called \textbf{Pydantic}. This is maybe the most important feature for our project. We used Pydantic to create 'schemas' for all of our API endpoints. This means the API automatically checks, validates, and cleans all data that comes from the user. If a user tries to create a train and sends ``abc`` for the \texttt{mileage}, Pydantic stops the request before it ever gets to our logic. This is a critical security layer. It protects our smart contract from bad data, and it saves us money by preventing transactions that would fail and still cost gas.
    
    \item \textbf{Developer Tools:} FastAPI automatically generates interactive API documentation (using OpenAPI and Swagger UI). This was very important for our development, as it allowed us to test our API endpoints very easily, without needing the frontend to be finished.
\end{itemize}

\subsection{API Structure and Request Flow}
\label{sec:backend_structure}

Our backend application is not one single file. We structured our code in a modular way to make it easy to understand. We used FastAPI's \texttt{APIRouter} to separate the three main parts of our system:

\begin{itemize}
    \item \textbf{Authentication Router:} This handles everything for user login, like \texttt{/token}.
    \item \textbf{Users Router:} This handles creating new user accounts, for example \texttt{POST /users}.
    \item \textbf{Assets Router:} This is the biggest and most important part. It handles all requests for \texttt{/trains}, \texttt{/wagons}, and \texttt{/equipment}.
\end{itemize}

The main application file just includes these routers. This makes our code very clean. When a new request comes from the user, the backend follows a clear process, which is shown in Figure \ref{fig:backend_flow}.

\begin{figure}[H]
\begin{center}
\includegraphics[width=13cm]{Figures/backend_request_flow.png} 
\caption{The flow of a user request through the backend API. The API acts as an orchestrator, first checking authentication and then deciding to use off-chain (SQLite) or on-chain (Blockchain) logic.}
\label{fig:backend_flow}
\end{center}
\end{figure}


\subsection{Off-Chain User and Authentication Service}
\label{sec:backend_auth}

A core part of our hybrid design is the separation of user data from asset data. It is a very bad and insecure idea to store user information, especially passwords, on a public blockchain. Therefore, we built a traditional, off-chain authentication service. This is a common and secure pattern for decentralized applications \cite{dapp_access_control}.

\subsubsection{Off-Chain Database}
For this service, we used a simple \textbf{SQLite} database. This database is managed by our backend using the \textbf{SQLAlchemy} library, which is an 'Object Relational Mapper' (ORM). The ORM lets us write our database models using Python classes. Our \texttt{User} model is very simple:
\begin{verbatim}
    class User(Base):
        id = Column(Integer, primary_key=True, index=True)
        email = Column(String, unique=True, index=True, nullable=False)
        hashed_password = Column(String, nullable=False)
        role = Column(String, default=``user``)
\end{verbatim}
This database only stores the user's email, a role (like 'admin' or 'user'), and a \textit{hashed} password. We use the \textbf{Passlib} library to ensure we never store the real password, only a secure hash.

\subsubsection{Authentication with JWT}
Our security is based on \textbf{OAuth2} and \textbf{JSON Web Tokens (JWT)}. The flow is simple:
\begin{enumerate}
    \item The user sends their email and password to the \texttt{/token} endpoint.
    \item The backend gets the user's data from the SQLite database.
    \item It uses \texttt{Passlib} to check if the password is correct.
    \item If it is correct, the backend creates a JWT. This token is a small piece of text that is ``signed`` by the backend with a secret key. It contains the user's ID.
    \item The backend sends this token back to the frontend.
\end{enumerate}
From this point, for every other request (like ``get all trains``), the frontend must include this token in the header. FastAPI automatically checks the signature of the token to make sure the user is who they say they are. This is how we ``protect`` our endpoints and make sure that only logged-in users can manage assets.

\subsection{Blockchain Orchestration Service}
\label{sec:backend_orchestration}

This is the most important job of the backend. The backend is the \textbf{orchestrator} that decides how and when to talk to the blockchain. The frontend application has no idea that a blockchain exists; it just knows how to talk to our API. This is a very good design because it makes our system simple.

All of this complex logic is in our 'asset controller' file. This controller is the only part of our system that has the blockchain's address, its ABI (Application Binary Interface), and the server's private key.

We have two different flows for blockchain communication: reading data and writing data.

\subsubsection{Reading Data (Read-Only Calls)}
Reading data from the blockchain is free and fast. When the user opens the 'Trains' page, the frontend calls our \texttt{GET /v1/trains} endpoint. The backend then performs these steps:

\begin{enumerate}
    \item It checks the user's JWT token to make sure they are logged in.
    \item It uses the \textbf{Web3.py} library to connect to our blockchain node (the Alchemy RPC endpoint).
    \item It loads the smart contract using its address and ABI.
    \item It makes a \textbf{`call()`} to the contract's \texttt{getAllTrains()} function. This is a 'view' function, so it is a read-only operation.
    \item The blockchain node runs the function and instantly returns the list of all trains.
    \item The backend formats this list as JSON and sends it to the frontend.
\end{enumerate}
This process is fast and costs no gas. The same logic is used for \texttt{getWagonDetail} and all other 'get' requests.

\subsubsection{Writing Data (Signed Transactions)}
This is the most complex and most important flow. Writing data (like adding a new train) costs gas and must be done very securely. When a user fills the form to add a new train, this is the flow:

\begin{enumerate}
    \item The frontend sends a \texttt{POST /v1/trains} request to our backend. The request body has the new train's data (name, manufacturer, etc.).
    \item \textbf{Validation:} First, Pydantic validates the data. It checks that \texttt{mileage} is a number and that \texttt{name} is a string. If not, the request is rejected.
    \item \textbf{Authentication:} Second, FastAPI checks the user's JWT token to make sure they are logged in and have permission (we could check for an 'admin' role here).
    \item \textbf{Transaction Building:} The backend's controller function now builds the transaction. It uses \texttt{web3.py} to call our contract's \texttt{addTrain} function.
    \item \textbf{Signing:} This is the key step. The backend server has a \textbf{private key} stored securely in an environment variable. It uses this key to \textit{sign} the new transaction. This signature proves to the blockchain that the backend (which we trust) is the one sending this request.
    \item \textbf{Sending:} The backend sends this \textit{signed transaction} to the blockchain via our Alchemy node.
    \item \textbf{Waiting:} The backend then 'waits' for the transaction to be mined and confirmed.
    \item When the blockchain confirms the transaction, it sends back a 'receipt'. The backend then sends a ``Success`` message to the frontend.
\end{enumerate}
This flow is very secure. The user's private key is never exposed. In fact, the user does not even have a key. The only key is the server's key, which is hidden. This makes the system much easier to use for non-technical railway staff.

\subsection{Data Validation Schemas}
\label{sec:backend_schemas}

As we mentioned, we use Pydantic to define 'schemas' for our data. This is a critical part of our backend. These schemas are Python classes that define what the data should look like.

For example, our \texttt{WagonCreate} schema looks like this:
\begin{verbatim}
    class WagonCreate(BaseModel):
        name: str
        wagon_type: str
        purchase_date: int
        origin_country: str
        manufacturer_address: str
        mileage: int
\end{verbatim}
When the frontend sends a request to create a new wagon, FastAPI automatically checks the data against this model. If the \texttt{mileage} is missing, or if the \texttt{name} is a number, Pydantic will automatically reject the request and send a helpful error message back to the frontend.

This is very important for two reasons. First, it is a key part of API security, as it stops 'bad' data from entering our system \cite{api_validation}. Second, it saves us money. If we let 'bad' data get to the smart contract, the transaction would fail, but it would \textit{still} cost us gas. By validating the data first, we ensure that we only send valid transactions to the blockchain. This makes our whole system more robust and more efficient.

% section for frontend implementation (React, UI, API calls)



\section{Frontend Application (User Interface)}
\label{sec:frontend_app}

The Frontend Application is the final layer of our three-tier architecture. It is the 'face' of our system and the only part that the end-users, like railway staff or maintenance crews, will ever interact with. The main goal of this layer is to provide a simple, fast, and secure user interface (UI) that hides all the complexity of the backend and the blockchain. The user does not need to know what a 'smart contract' is, they only need to know how to add a wagon or update a maintenance record.

We developed this application as a \textbf{Single-Page Application (SPA)}. This is a modern approach for web applications, where the user loads the application only one time. After that, when the user navigates between pages (like from '/trains' to '/wagons'), the application does not reload. It just changes the content on the page. This makes the application feel very fast and responsive, almost like a desktop application.

\subsection{Core Technologies and Rationale}
\label{sec:frontend_tech}

We choice our technologies very carefully to build a modern and maintainable system.

\begin{itemize}
    \item \textbf{React and TypeScript:} The main library for our UI is \textbf{React}. We chose React because it is based on a \textbf{component architecture}. This means we can build small, reusable pieces of code. For example, we built one \texttt{WagonForm} component, and we can use this same component for both 'creating a new wagon' and 'editing an old wagon'. This saves a lot of time and reduces bugs. We also used \textbf{TypeScript} instead of plain JavaScript. TypeScript adds 'types' to our code, which helps us catch many errors before we even run the application. For a big project like this, type safety is very important \cite{component_architecture_benefits}.

    \item \textbf{Styling with TailwindCSS:} For the visual design, we used \textbf{TailwindCSS}. This is a 'utility-first' CSS framework. Instead of writing separate CSS files, we build the design directly in our components. This made our development much faster and it let us create a custom, responsive design that looks good on both desktop and mobile, without being stuck with a heavy library like Bootstrap.
    
    \item \textbf{Routing:} To manage the different pages of our SPA, we used the \textbf{React Router} library. This library connects a URL (like \texttt{/dashboard}) to the correct React component (like our \texttt{Dashboard} page component).
\end{itemize}

\subsection{State Management Strategy}
\label{sec:frontend_state}

A complex application needs to manage a lot of 'state'. State is all the data that can change, like the list of trains, or if a user is logged in. We divided our state into two types: Server State and Client State.

\subsubsection{Server State with React Query}
This was one of our most important design decisions. For all data that comes from our backend API, we used \textbf{React Query} (also known as TanStack Query). In older applications, developers would use 'Redux' or 'useState' to store this data, which is very complex and needs a lot of manual code.

React Query is a modern data-fetching library that is much simpler. It treats data from the API as 'server state' and it handles everything for us \cite{data_fetching_libraries}.
\begin{itemize}
    \item \textbf{Caching:} When we fetch the list of trains, React Query saves it in a cache. If the user moves to another page and comes back, the list loads instantly from the cache, it doesn't need to ask the server again.
    \item \textbf{Automatic Updates:} The best feature is 'stale-while-revalidate'. This means it shows the old, cached data first (so the page is fast), but it still fetches new data in the background. When the new data arrives, it updates the page.
    \item \textbf{Mutations:} When we need to change data (like creating a new train with our \texttt{TrainForm}), we use a 'mutation'. We tell React Query to send the \texttt{POST} request to our API. After the mutation is successful, we can tell it to automatically 'invalidate' the cache for ``all trains``. This makes React Query fetch the list of trains again, so the user's new train appears in the list right away.
\end{itemize}
Using React Query made our component code much cleaner and simpler, and it made the application feel much faster to the user.

\subsubsection{Client State with React Context}
For the state that is not from the server, like ``is the user currently logged in?``, we used React's built-in \textbf{Context API}. We created an \texttt{AuthContext}. This context wraps our entire application. When a user logs in, the \texttt{Login} page calls the API, gets the JWT token, and saves this token in the \texttt{AuthContext}. Now, any other component in the application can ask this context, ``is the user authenticated?``. This is how we manage security on the frontend.

\subsection{Application Structure and User Workflow}
\label{sec:frontend_workflow}

The structure of our application is defined by its pages and components. The main application file defines all the available routes.

\subsubsection{Security with Protected Routes}
Security is the first step. We created a special component called \texttt{ProtectedRoute}. This component wraps all our main pages, like \texttt{/trains} and \texttt{/dashboard}. Before it shows the page, it checks our \texttt{AuthContext}. If the user is not authenticated, this component will immediately redirect the user to the \texttt{/login} page. This makes it impossible for an unauthorized person to see any of the asset data.

\subsubsection{Main Pages and Functionality}
Our application provides several key pages for the railway staff:
\begin{itemize}
    \item \textbf{Login Page:} A simple form to send a username and password to our backend's \texttt{/token} endpoint to get a JWT.
    
    \item \textbf{Dashboard Page:} This is the main landing page. It shows a high-level overview of the entire system. We built several data visualization components here, like \texttt{PieChartByCountry}, which shows the distribution of asset manufacturers. We also have map components that can show the location of suppliers, which is useful for supply chain tracking.
    \item % ----- EXISTING DASHBOARD FIGURE -----
A screenshot of the main ``Equipment`` page is shown in Figure \ref{fig:equipment_page}. This shows the main user interface for managing assets, including the list of equipment and the interactive map.

\begin{figure}[H]
\begin{center}

\includegraphics[width=0.9\textwidth]{Figures/Equipments-dashboard.png} 
\caption{A screenshot of the main Equipment Management page in our system.}
\label{fig:equipment_page}
\end{center}
\end{figure}
% ----- END OF EXISTING FIGURE -----
    
    \item \textbf{Asset Management Pages (\texttt{/trains}, \texttt{/wagons}, \texttt{/equipment}):} These are the main ``work`` pages. Each page shows a table or list of all the assets, fetched from our API using React Query. From here, a user can click a button to open a form (like \texttt{TrainForm} or \texttt{WagonForm}) to create a new asset or edit an existing one.
    
    \item \textbf{Detail Pages (\texttt{/equipment/:id}):} We also have detail pages for when a user needs more information. This page shows all the details for one single piece of equipment, and it might also fetch and show the parent wagon and train that it belongs to.
\end{itemize}

% ----- NEW FIGURE (DETAIL PAGE) -----
As shown in Figure \ref{fig:equipment_detail_page}, the detail page provides a full summary of the component. A key feature we implemented is the QR code. A mechanic can scan this label to find the exact location of a broken part inside the wagon, using our schematic addressing format. This page is also designed to be printable, so it can act as a physical maintenance paper or ``work order`` for a mechanic who is going to fix the part.

\begin{figure}[H]
\begin{center}

\includegraphics[width=0.4\textwidth]{Figures/Equipments-detail.png} 
\caption{A screenshot of the Equipment Detail page. This page shows all asset data, the parent train and wagon, and a QR code for location tracking and printing.}
\label{fig:equipment_detail_page}
\end{center}
\end{figure}
% ----- END OF NEW FIGURE -----

\subsubsection{Example Maintenance Workflow}
We can describe a full workflow for a user:
\begin{enumerate}
    \item A maintenance mechanic logs in on the \textbf{Login Page}. The app saves their token in the \texttt{AuthContext}.
    \item They are sent to the \textbf{Dashboard}. They see a chart that shows ``5 pieces of equipment are not operational``.
    \item They click on the \textbf{Equipment Page}. The page uses React Query to call our backend \texttt{GET /v1/equipment} and shows a list of all equipment. The mechanic filters this list to see the broken parts.
    \item They find the broken part (e.g., 'Brake Unit 105') and go to the train to fix it.
    \item After fixing it, they come back to the app and click 'Edit' on that part.
    \item The app opens the \texttt{EquipmentForm} component, filled with the data for 'Brake Unit 105'.
    \item The mechanic changes the \texttt{isOperational} status from 'false' to 'true' and clicks 'Save'.
    \item The app uses a React Query 'mutation' to send a \texttt{PUT /v1/equipment/105} request to our backend.
    \item The backend validates the request, sends the transaction to the blockchain, and when it is confirmed, it sends ``Success`` back to the frontend.
    \item The mutation is successful, so React Query automatically refetches the equipment list. The list updates, and 'Brake Unit 105' now shows its status as 'Operational'.
\end{enumerate}

For example, as seen in the screenshot, a location code of \texttt{Z3-L-F} means the part is in ``Zone 3, on the Left side, at Floor level``. This simple, standardized code makes it very efficient for a mechanic to find a specific component inside a complex train wagon.
A screenshot of this edit form is shown in Figure \ref{fig:equipment_edit_page}. This form allows the user to update all the key information for the asset, including its maintenance status and its specific physical location inside the wagon.

We designed a special schematic addressing format for the \texttt{locationCode} to help mechanics find parts much faster. This code is stored in the smart contract and is a key part of our system. The format is \texttt{Z\{zone\}-(L|R)-(O|F|U)}.
\begin{itemize}
    \item \texttt{Z} stands for the Zone (e.g., Z1, Z2, Z3...).
    \item \texttt{L|R} stands for the side (Left or Right).
    \item \texttt{O|F|U} stands for the vertical level (Overhead, Floor, or Underframe).
\end{itemize}

    % ----- EXISTING EDIT FORM FIGURE -----
\begin{figure}[H]
\begin{center}

\includegraphics[width=0.4\textwidth]{Figures/Equipments-edit.png} 
\caption{A screenshot of the ``Edit Equipment`` form in our application. This shows the fields for updating maintenance status and the schematic location code.}
\label{fig:equipment_edit_page}
\end{center}
\end{figure}
% ----- END OF EXISTING FIGURE -----



\subsection{Progressive Web App (PWA) for Mobile Access}
\label{sec:frontend_pwa}

A very important part of our project is supporting mobile users. A railway mechanic or inspector is not always at a desk. They are in the field, in a maintenance yard, or even in a tunnel where the internet connection is bad. They cannot depend on a normal website.

To solve this, we built our frontend as a \textbf{Progressive Web App (PWA)}. A PWA is a website that can be ``installed`` on a user's phone (Android or iOS) or desktop, just like a native app from the App Store. This gives us the best of both worlds: we have one codebase (our React app) that works on all platforms. This is a very common strategy in modern enterprise applications \cite{pwa_enterprise}.

We implemented this using two key files:
\begin{itemize}
    \item \textbf{\texttt{manifest.json}:} This is a simple JSON file that tells the phone's operating system about our application. It defines the app's name (``Train Inventory``), and its theme colors. This is what allows the ``Add to Home Screen`` prompt to appear.
    
    \item \textbf{\texttt{service-worker.js}:} This is the ``brain`` of the PWA. A service worker is a special script that the browser runs in the background, separate from the web page. We configured our service worker to do \textbf{offline caching}. When the user first loads the app, the service worker saves all the main application files (the HTML, CSS, and JavaScript) to the device.
\end{itemize}

This provides a huge benefit: \textbf{Offline Access}. If a mechanic opens the app on their phone in an area with no internet, the service worker will still load the application ``shell`` from the cache. The user can still open the app, see the layout, and maybe even see the data that was cached the last time they were online. This makes the application much more reliable for real-world use \cite{pwa_offline}. This offline capability is a key feature that makes our solution much more practical than a standard website.