Venti
Venti was developed in 2018 as an undergraduate thesis project aimed at addressing specific challenges within the Venezuelan financial landscape: severe cash scarcity, very slow POS systems and cumbersome bank transfer processes. It envisioned a peer-to-peer (P2P) payment system allowing users to send and receive money instantly via a simple Android application. A core requirement of the thesis was the integration of blockchain technology (blockchain was all the rage at the time) to ensure the integrity and immutability of transaction records.
This post offers a look into the technical architecture that powered it.
What and Why
As an academic project, Venti was mainly a proof of concept that didn’t require the usual
As usual with academic projects, building Venti involved limited timeframes and the need to fulfill specific objectives (like implementing a blockchain), while still aiming for a functional and user-friendly system. As a proof-of-concept, it didn’t dwell too much on things like scalability, though it did need to be something that could realistically grow into an actual product. The technology choices centered around:
- Rapid Development: Given the project timeline, technologies facilitating quick iteration were essential. Python and Django, known for their speed of development, were key choices.
- Ease of Deployment & Cost: Simplicity in deployment was important. PythonAnywhere was chosen as a hosting platform due to its ease of use for Python/Django applications and cost-effectiveness (i.e. it’s free) for a project of this scale.
- Fulfilling Core Requirements: The primary academic goal was to explore blockchain within a transactional system, while solving a real problem in Venezuela. This drove the design of a custom blockchain layer integrated directly into the backend logic and database.
- Mobile Platform: For the user interface, native Android development with Java was selected due to its wide reach in the target market (Venezuela) and the availability of mature development tools (Android Studio) and extensive documentation, crucial for developers relatively new to mobile app creation.
- Security Considerations: Handling user funds, even in a prototype, requires careful security measures. This included secure authentication, encryption of sensitive data (like credit card details before sending to the payment processor), and the inherent security features of the blockchain implementation.
This allowed Venti to meet its academic goals while delivering a working prototype demonstrating the core P2P payment functionality.
General Overview
Venti’s architecture consists of a native Android mobile application for user interaction, a backend API managing business logic and the blockchain, a relational database for persistence, and integration with an external payment gateway. The backend was hosted on PythonAnywhere.
graph TD
subgraph PythonAnywhereHosting [PythonAnywhere Hosting]
BackendAPI[Backend API Django/DRF + Blockchain Logic];
DB[(MySQL)];
WebServer[NGINX];
AppServer[uWSGI];
end
User(User's Mobile Device) --> App[Android App Java];
App -- HTTPS REST API --> WebServer;
WebServer --> AppServer;
AppServer --> BackendAPI;
BackendAPI --> DB;
BackendAPI --> PaymentGateway[Instapago API];
BackendAPI --> EmailAPI[Gmail API for Password Reset];
style App fill:#D6EAF8,stroke:#333,stroke-width:2px,color:#333
style BackendAPI fill:#D5F5E3,stroke:#333,stroke-width:2px,color:#333
style DB fill:#FCF3CF,stroke:#333,stroke-width:2px,color:#333
style WebServer fill:#EAECEE,stroke:#333,stroke-width:1px,color:#333
style AppServer fill:#EAECEE,stroke:#333,stroke-width:1px,color:#333
style PaymentGateway fill:#EBDEF0,stroke:#333,stroke-width:2px,color:#333
style EmailAPI fill:#EBDEF0,stroke:#333,stroke-width:2px,color:#333
The system was designed to provide a seamless user experience for sending money, requesting funds, managing bank accounts/cards, and viewing transaction history, all underpinned by the security layer provided by the blockchain.
Frontend: The Mobile App (Android Native)
Users interacted with Venti through a dedicated Android application.
- Framework: Built natively for Android using the Android SDK.
- Language: Developed using Java.
- IDE: Android Studio was the primary development environment.
- API Interaction: Communicated with the backend via a REST API using Retrofit 2 and GSON for handling HTTP requests and JSON parsing. Glide was used for efficient image loading.
- Local Storage: Utilized Android’s
SharedPreferencesfor storing user session tokens (from Knox), profile information, and encrypted credit card details (after initial encryption by the server). - UI/UX: Followed Material Design guidelines. Key screens included Login/Registration, Transaction History, Send/Request Money flows, Account/Card Management, and Profile Settings. Implemented
RecyclerViewfor handling lists like transaction history. - Key Features: User authentication, profile creation/editing, adding bank accounts and credit cards (data encrypted before storage/use), sending/requesting funds, accepting/rejecting requests, viewing transaction history and account activity (recargas/canjeos), balance display.
The application aimed for intuitiveness, minimizing the steps required for common actions like sending money.
Backend: Django, DRF, and the Blockchain Core
Venti’s backend logic was built on a Python stack using Django and Django REST Framework (DRF).
- Core: Python 3.6, Django, and DRF.
- Structure: Organized as a single Django project (
venti) containing the main application logic within a single app (ventiapp). - API: Exposed RESTful endpoints using DRF’s
ViewSets(for standard CRUD operations on models likeUser,Profile,BankAccount) and customAPIViewclasses (for specific actions likeCredito,Canjeo,MyProfile,ResetPassword). - Authentication: Employed
django-knoxfor token-based authentication after login. A custom authentication class handled the initial username/password login. JWT was used for password reset token generation (RequestResetPassword,ResetPasswordviews). - Database Interaction: Primarily used the Django ORM for interacting with the MySQL (production) and SQLite (development) databases.
- Security:
- Credit card numbers and CVCs sent from the app were encrypted using Fernet symmetric encryption before being sent to the Instapago API (
Creditoview,EncriptarTarjetaview). The Fernet key was stored server-side. Raw card details were not stored persistently on the server, only on the mobile app.
- Credit card numbers and CVCs sent from the app were encrypted using Fernet symmetric encryption before being sent to the Instapago API (
- Image Handling: Used
django-imagekitto process uploaded profile images (resizing to 300x300 and converting to WEBP format) for optimization (Profilemodel,helpers.py). - External Integrations:
- Payments: Integrated with Instapago’s API using the
requestslibrary to process credit card top-ups (Creditoview). Bank withdrawals (Canjeoview) generated transaction records and were intended to feed into a semi-manual batch file process for bank transfers1. - Email: Used the Google Gmail API via
google-api-python-clientandoauth2clientfor sending password reset emails (helpers.py,RequestResetPasswordview).
- Payments: Integrated with Instapago’s API using the
graph LR
subgraph BackendCore [Backend Core on PythonAnywhere]
DjangoApp[Django/DRF App w/ Blockchain Logic]
end
subgraph MiddlewareAndState [State & Dependencies]
DB[(MySQL)]
end
subgraph ExternalServices [External Services]
Instapago[Instapago API]
GmailAPI[Google Gmail API]
end
%% Connections
DjangoApp --> DB;
DjangoApp --> Instapago;
DjangoApp --> GmailAPI;
%% Apply styles
style DjangoApp fill:#D5F5E3,stroke:#333,stroke-width:2px,color:#333
style DB fill:#FCF3CF,stroke:#333,stroke-width:2px,color:#333
style Instapago fill:#EBDEF0,stroke:#333,stroke-width:2px,color:#333
style GmailAPI fill:#EBDEF0,stroke:#333,stroke-width:2px,color:#333
The Venti Blockchain Implementation
When the thesis project was initially proposed, the blockchain was a value add both from an academic (learning about a technology that was in vogue and growing) and from a product (increasing trust and “security”) perspective. As the project evolved, some of the characteristics of actual blockchains clashed with the problems the app was trying to solve. First of all, compute power was virtually non existent for this project, which meant that until a bigger community started mining, it would be trivially easy to perform a 51% attack. Second, part of the informal requirements for the project were for it to have a path to become an actual profitable venture, which was made more difficult if the core of the business revolved around a blockchain that wouldn’t be controlled by the company. Third and last, when trying to replace bank transfers, it would be a harder sale for users if all their transactions were public by default with what they would perceive as little gain. On the other hand, since a blockchain was already part of the approved proposal, the decision was made to implement what was called a “private” blockchain: a blockchain controlled by a single entity (thus losing the whole “decentralized” thing), but keeping some of the transparency it offers. This succeeded well on the academic goal of learning about blockchains, while still keeping some of the value add for the product with a proposed public verification mechanism.
- Purpose: To create an immutable, verifiable record of all transactions within the system, enhancing trust and security against tampering (both internal and external).
- Type: Private Blockchain. All logic for creating and managing the chain resided within the backend server code. There was no distributed consensus mechanism like Proof-of-Work or Proof-of-Stake.
- Structure & Integrity:
- Transaction Hashing: When a
Transactionwas successfully processed (e.g., funds moved between user balances), its core details (ID, sender, receiver, amount, message, timestamp) were serialized into a standardized JSON format. A SHA256 hash of this JSON string was computed and stored alongside the transaction record in theTransactiondatabase table (handled withinTransactionSerializer). - Block Creation: Blocks were generated automatically by the system. After every 5 new transactions were recorded (checked within the
TransactionSerializer’screatemethod), the system triggered the creation of a newBlockchainentry. - Linking & Signatures: The crucial element for immutability was the cryptographic linking. Each new
Blockchainblock stored:- References to the first and last
TransactionIDs included in that block. - A precise timestamp of block creation.
- The RSA-2048 signature of the previous block’s hash (
prev_hash). This signature was generated using a private RSA key (Secrets.PRIVATE_RSA_KEY) kept only on the server. This acts as a “proof of identity” for the block creator (the Venti system itself). - The SHA256 hash of the current block’s entire contents (
this_hash), which included its own metadata, the concatenation of all transaction hashes within its range, and the signed hash of the previous block. This was calculated by theBlockchainSerializer.
- References to the first and last
- Immutability: Because each block contained a cryptographically signed reference to the previous one, modifying any past transaction or block would require re-calculating and re-signing all subsequent blocks. Without the private key, this is computationally infeasible, making the chain tamper-evident.
- Genesis Block: A special procedure within the
TransaccionInicialSerializerhandled the creation of the first transaction (a system-internal initialization) and the first block, using a predefined value (“Bloque Inicial”) for theprev_hashfield.
- Transaction Hashing: When a
- Storage: Both individual transaction hashes (
Transaction.hash) and the block metadata (Blockchainmodel instance) were stored directly in the primary MySQL database. - Verification (Conceptual): The thesis proposed that external verification could be possible without revealing sensitive transaction details. An auditor (or even a user verifying their own history) could:
- Recalculate the SHA256 hash of a specific transaction’s details.
- Verify this matches the
hashstored with theTransactionrecord. - Obtain the
Blockchainblock data (containing timestamps, transaction ranges,this_hash, and the signedprev_hash). - Using the publicly available Venti public RSA key, verify the signature (
prev_hash) against thethis_hashof the preceding block. - Concatenate all transaction hashes within the block’s range, combine with block metadata and the verified (decrypted) previous hash, and re-calculate the SHA256 hash of the current block to ensure it matches the stored
this_hash. This process could confirm the integrity of the chain and the inclusion of specific transactions without exposing sender/receiver details publicly.
graph TD
subgraph BlockchainProcess [Blockchain Generation Flow]
NewTx[New Transaction Saved] --> HashTx[Calculate Tx Hash SHA256];
HashTx --> StoreTxHash[Store Hash in Transaction Table];
StoreTxHash --> CheckCount{Tx Count >= 5?};
CheckCount -- Yes --> SignPrevHash[Sign Previous Block Hash with Private RSA Key];
SignPrevHash --> CreateBlock[Create New Block Metadata - Tx Range, Timestamp, Signed Prev Hash];
CreateBlock --> AggregateTxHashes[Aggregate Hashes of Txs in Block];
AggregateTxHashes --> HashBlock[Calculate Current Block Hash SHA256 - Metadata + Tx Hashes + Signed Prev Hash];
HashBlock --> StoreBlock[Store Block Metadata + Block Hash in Blockchain Table];
CheckCount -- No --> End;
end
style NewTx fill:#D5F5E3,stroke:#333,stroke-width:2px,color:#333
style CheckCount fill:#FFF3CD,stroke:#333,stroke-width:2px,color:#333
style SignPrevHash fill:#D6EAF8,stroke:#333,stroke-width:2px,color:#333
style HashBlock fill:#D6EAF8,stroke:#333,stroke-width:2px,color:#333
style StoreTxHash fill:#FCF3CF,stroke:#333,stroke-width:2px,color:#333
style StoreBlock fill:#FCF3CF,stroke:#333,stroke-width:2px,color:#333
This custom implementation provided the required blockchain features for the thesis, focusing on data integrity through hashing and asymmetric cryptography signatures within a centralized system architecture.
Database: MySQL & SQLite
The primary data store for production was MySQL, hosted on PythonAnywhere. SQLite was used for local development.
- Type: Relational database.
- Management: Database schema defined using Django models (
User,Profile,Email,PhoneNumber,BankAccount,Transaction,Request,Blockchain). Schema changes managed via Django migrations. - Interaction: Accessed exclusively through the Django ORM.
- Key Models: Stored user details, balances, contact info, bank accounts, individual transactions (with their hashes), payment requests, and the blockchain metadata itself.
- Operations: Ran as a single instance managed by PythonAnywhere. The thesis notes the process for generating withdrawal batch files but doesn’t detail automated database backups beyond standard Django operations.
Infrastructure & Hosting: PythonAnywhere
The Venti backend was hosted entirely on PythonAnywhere, a Platform-as-a-Service (PaaS) environment simplifying Python web application deployment.
- Platform: PythonAnywhere (running on AWS EC2 infrastructure).
- Web Server: NGINX, configured by PythonAnywhere, served static files (like profile images processed by ImageKit) and proxied dynamic requests. It also handled HTTPS redirection.
- Application Server: uWSGI, communicating with NGINX and running the Django application code within a Python virtual environment.
- Deployment: Updates were typically done manually by pulling the latest code from a Git repository (like GitHub) via the PythonAnywhere console and reloading the web application. No containerization (like Docker) was used.
- Environment: Utilized Python virtual environments to manage dependencies separate from the system Python installation.
graph TD
subgraph PythonAnywhereInstance [PythonAnywhere Hosted Environment]
direction LR
NGINX[NGINX Web Server] --> uWSGI[uWSGI App Server];
uWSGI --> DjangoApp[Django/DRF Application];
DjangoApp --> PythonVenv[Python Virtual Env];
DjangoApp --> MySQLDB[(MySQL Database)];
NGINX -- Serves --> StaticFiles[Static Files /media/];
end
style PythonAnywhereInstance stroke-width:2px
style NGINX fill:#EAECEE,stroke:#333,stroke-width:1px,color:#333
style uWSGI fill:#EAECEE,stroke:#333,stroke-width:1px,color:#333
style DjangoApp fill:#D5F5E3,stroke:#333,stroke-width:1px,color:#333
style PythonVenv fill:#FDF2E9,stroke:#333,stroke-width:1px,color:#333
style MySQLDB fill:#FCF3CF,stroke:#333,stroke-width:1px,color:#333
style StaticFiles fill:#FDEBD0,stroke:#333,stroke-width:1px,color:#333
This setup provided a straightforward way to get the Django application running online without managing server infrastructure directly.
Networking & Edge: Simple HTTPS
Networking was relatively simple, relying on PythonAnywhere’s infrastructure.
- Traffic Flow: User requests from the Android app connected over the internet via HTTPS to PythonAnywhere’s load balancers (implicitly), which routed traffic to the NGINX server configured for the Venti application. NGINX then passed the request to uWSGI and the Django application.
- Security: HTTPS was enforced by configuring NGINX (via PythonAnywhere’s interface) to redirect HTTP traffic. SSL certificates were automatically managed by PythonAnywhere for
*.pythonanywhere.comsubdomains. No additional CDN or WAF was employed. - Performance: Relied on the basic performance of PythonAnywhere’s hosting tiers and the efficiency of the Django application itself. Image optimization via ImageKit helped reduce load times for profile pictures.
sequenceDiagram
participant User
participant PAEdge as PythonAnywhere Edge/LB
participant NGINXCont as NGINX @PythonAnywhere
participant uWSGICont as uWSGI @PythonAnywhere
participant DjangoCont as Django App @PythonAnywhere
User->>PAEdge: HTTPS Request venti.pythonanywhere.com
PAEdge->>NGINXCont: Forward Request
NGINXCont->>uWSGICont: Forward to App Server
uWSGICont->>DjangoCont: Execute Django View
DjangoCont-->>uWSGICont: Response
uWSGICont-->>NGINXCont: Response
NGINXCont-->>PAEdge: Response
PAEdge-->>User: HTTPS Response
Parting thoughts
Venti successfully met its primary goal as an undergraduate thesis: demonstrating the feasibility of a P2P payment application incorporating blockchain technology within the Venezuelan context. The use of Django and DRF allowed for rapid development of the core API, while native Android provided the user interface. The custom blockchain implementation, while perhaps not production-ready in terms of performance or standard practices compared to established public chains, fulfilled the academic requirement and provided a functional layer of transaction immutability secured by RSA signatures.
The project highlighted the potential for such systems while also underscoring the real-world challenges, particularly around seamless integration with the existing banking infrastructure in a complex regulatory environment1. It stands as an interesting case study in applying blockchain concepts to a specific regional problem, built with practical, accessible technologies.
