Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Milestone 2 #5

Merged
merged 25 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
postgresql password: postgres
- name: Build
working-directory: ./pcidss
run: cargo build --verbose
run: cargo build --verbose
- name: Run tests
working-directory: ./pcidss
run: cargo test --verbose
run: cargo test --workspace --exclude oracle-e2e-tests
24 changes: 24 additions & 0 deletions .rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Basic
edition = "2021"
hard_tabs = true
max_width = 100
use_small_heuristics = "Max"
# Imports
imports_granularity = "Crate"
reorder_imports = true
# Consistency
newline_style = "Unix"
# Misc
chain_width = 80
spaces_around_ranges = false
binop_separator = "Back"
reorder_impl_items = false
match_arm_leading_pipes = "Preserve"
match_arm_blocks = false
match_block_trailing_comma = true
trailing_comma = "Vertical"
trailing_semicolon = false
use_field_init_shorthand = true
# Format comments
comment_width = 100
wrap_comments = true
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"rust-analyzer.checkOnSave": true
}
184 changes: 184 additions & 0 deletions DEMO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# Demo for M2

## Run the node

To run the node, you need to have the following dependencies installed:

```bash
docker run -it -p 9944:9944 kingleard/iso8583-chain --dev --tmp --unsafe-rpc-external --rpc-cors=all --rpc-methods=unsafe -loffchain-worker
```

Insert the offchain worker key to substrate node:

```bash
curl -H "Content-Type: application/json" \
--data '{ "jsonrpc":"2.0", "method":"author_insertKey", "params":["'"iso8"'", "'"news slush supreme milk chapter athlete soap sausage put clutch what kitten"'", "'"0xd2bf4b844dfefd6772a8843e669f943408966a977e3ae2af1dd78e0f55f4df67"'"],"id":1 }' \
"http://0.0.0.0:9944"
```

Then, you can access the explorer [here](https://polkadot.js.org/apps/?rpc=ws://0.0.0.0:9944#/explorer).

## Run the infrastracture

For demonstration purposes, `docker-compose` configuration is provided. It will start the following services:

- [Demo merchant application](./interface/README.md)
- [Payment Processor Server](./payment-processor/README.md)
- PCIDSS compliant [oracle](./pcidss/README.md)
- [ISO-8583 compliant Substrate chain](https://github.com/subclone/iso8583-chain)

To start the demo, first pull the images:

```bash
docker-compose pull
```

Then start the services:

```bash
docker-compose up
```

You will be able to access the demo merchant application at `http://localhost:3002`.

## Milestone Goals

1. On-chain addresses can be associated with bank accounts
2. On-chain balance is synced with off-chain balance, off-chain ledger serves as a source of truth
3. It is possible to trigger ISO-8583 transactions (both payment and reversal) both from POS and on-chain transactions
4. On-chain messages are converted to ISO-8583 format and processed by the oracle
5. Oracles settle finalised ISO-8583 transactions on-chain

## Demo flow

Demo of on-chain extrinsics and their interaction with the oracle gateway is documented [here](https://github.com/subclone/iso8583-chain/blob/main/DEMO.md). This demo is aimed at showing the user facing side of the infrastracture, and in general the end product of all components.

### Prerequisites

First and foremost, insert the offchain worker key to substrate node, in case you didn't yet:

```bash
curl -H "Content-Type: application/json" \
--data '{ "jsonrpc":"2.0", "method":"author_insertKey", "params":["'"iso8"'", "'"news slush supreme milk chapter athlete soap sausage put clutch what kitten"'", "'"0xd2bf4b844dfefd6772a8843e669f943408966a977e3ae2af1dd78e0f55f4df67"'"],"id":1 }' \
"http://localhost:9944"
```

#### Accounts and their roles

- `Alice`, `Bob` - oracle wallets, i.e used for submitting finality of ISO-8583 by PCIDSS oracles.
- `Charlie`, `Dave`, `Demo User` - wallets that are associated with corresponding bank account, come with balance and ready for using.
- `Alice_stash`, `Bob_stash` - wallets that will be used to demo associating on-chain accounts to bank account
- `Eve` - an account with expired card
- `5HRD6MDjy9XjX6gNhj7wSAinvpNw1DptfR73LZBz68zH4Gex` - wallet associated with merchant's bank account, i.e it will receive payments from the checkout page.

Use these dev bank accounts for testing payment and reversal. Note that the `Demo User` account has a private key, which you have to add to `Polkadot.js` extension if you want to use it to sign transactions.

```json
[
{
"name": "Charlie",
"card_number": "4169812345678903",
"expiration_date": "03/28",
"cvv": "125"
},
{
"name": "Dave",
"card_number": "4169812345678904",
"expiration_date": "03/28",
"cvv": "126"
},
{
"name": "Demo User",
"card_number": "4169812345678900",
"expiration_date": "03/28",
"cvv": "123",
"private_key": "intact start solar kind young network dizzy churn crisp custom fuel fabric"
}
]
```

Use these predefined dev bank accounts for testing. They are not associated with any on-chain account.

```json
[
{
"name": "Alice_stash",
"card_number": "4169812345678908",
"expiration_date": "03/28",
"cvv": "999"
},
{
"name": "Bob_stash",
"card_number": "4169812345678909",
"expiration_date": "03/28",
"cvv": "888"
}
]
```
NOTE: expiration date is always 4 years away from current time, i.e 03/2028 assuming we are in 03/2024.

Now, everything is ready for the demo.

### On-chain address association

By opening the demo merchant application, you will see the simulation of a bank dashboard, where you can see basic details about the bank account and its transactions. To ease the testing, there is a button on the top right corner that allows you to switch between wallets. You can use development accounts to simulate different scenarios.

![Screenshot 2024-03-21 at 22 11 18](https://github.com/subclone/payment-processor/assets/88332432/02f748f4-8c1d-491e-b2aa-887b27fc8e24)

When an address you switched to is not associated with any bank account, you will be redirected to the registration page, which will ask for your card details. After submitting the form with one of the predefined bank account details from above, you will be redirected back to the dashboard. Registration request is ISO-8583 message, which is processed and settled on chain by the oracle.

![Screenshot 2024-03-21 at 22 25 17](https://github.com/subclone/payment-processor/assets/88332432/d2f04aa6-df0c-4218-a523-bd30a9957eed)

On-chain association:

<img width="1712" alt="Screenshot 2024-03-21 at 22 25 48" src="https://github.com/subclone/payment-processor/assets/88332432/55fc127d-30af-49d6-8153-fecac988f627">

### On-chain balance synchronization

If you check for account balances from the explorer, you will see that they match what is shown on the dashboard. And offchain worker periodically (every 10 blocks) runs and updates the latest balance of accounts from the bank backend.

<img width="1712" alt="Screenshot 2024-03-21 at 22 29 03" src="https://github.com/subclone/payment-processor/assets/88332432/899cda0c-8528-48e9-83ce-11d3c4c221b0">

![Screenshot 2024-03-21 at 22 29 30](https://github.com/subclone/payment-processor/assets/88332432/639a7ccc-fc3f-4998-958e-d8ac41990852)

### ISO-8583 transactions

### Payment
Now, to actually see how on-chain balance is synced and how ISO-8583 transactions are processed, we can use the checkout page. It is a simple form that asks for card details in a checkout session, i.e when paying for some goods. It is a simulation of a POS terminal, part of delivery of Milestone 1. Submit the form with any of the dev bank account details, here we will use `Charlie`:

![Screenshot 2024-03-21 at 22 32 54](https://github.com/subclone/payment-processor/assets/88332432/b7f4df39-5782-408e-a6c6-0402ba7963b9)

It will forward us back to the Dashboard where we can see that the balance has been decreased and off-chain ledger transaction is recorded.

![Screenshot 2024-03-21 at 22 33 45](https://github.com/subclone/payment-processor/assets/88332432/ca9c44ba-832b-4821-96c6-01526a819246)

By checking the explorer, you will notice that offchain worker detects change in the balance and updates on-chain balance after couple of blocks (10 blocks ~30s currently). This is not a limitation of the system, because the source of truth is always off-chain ledger.

<img width="1451" alt="Screenshot 2024-03-21 at 22 35 31" src="https://github.com/subclone/payment-processor/assets/88332432/e0ad5ea4-de32-43e4-a79b-3d9a25b8adc7">

With Milestone 2, we added the ability to trigger ISO-8583 transactions with on-chain transaction. To do that, you have to switch to `Crypto` tab and click on `Pay` button. It will trigger an extrinsic which you have to
sign and submit (if you are using development accounts it will not prompt signature, i.e `Alice`, `Charlie`, etc.)

![Screenshot 2024-03-21 at 23 57 32](https://github.com/subclone/payment-processor/assets/88332432/0ab6d5d4-30c9-4699-a954-2377287fa9ea)

Make sure you have selected a proper wallet, in the screenshot above it is `Dave`.

#### Reversal

Reversal can be triggered in the dashboard, similar to how it was after the Milestone 1.

![Screenshot 2024-03-22 at 0 09 07](https://github.com/subclone/payment-processor/assets/88332432/ea3670b5-72ea-42e5-975c-a579c9216a37)

Note that this is an off-chain ledger transaction and it can only be reversed once.

For triggering reversal using Polkadot.js, take a look at the [Demo of ISO-8583 chain](https://github.com/subclone/iso8583-chain/blob/main/DEMO.md)

### Settlement

Note that in the explorer, you will initially see `InitiateTransfer` event, and after couple of blocks `ProcessedTransaction` event. This is because of event driven nature of current implementation. Most of the times, however, transaction is initiated and processed in the next or 2 blocks later. Since we are using off-chain ledger as a source of truth, on-chain settlement's speed is not really important, however it is important for UX since wallets need to be notified when transaction is settled (i.e by tracking `ProcessedTransaction` event).

<img width="672" alt="Settlement" src="https://github.com/subclone/payment-processor/assets/88332432/ceb17bfc-63bf-4456-bb74-e5954eea43b3">

### Transfers between wallets

For transferring between wallets, please refer to the [Demo of ISO-8583 chain](https://github.com/subclone/iso8583-chain/blob/main/DEMO.md)
11 changes: 0 additions & 11 deletions Makefile

This file was deleted.

18 changes: 15 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@ This is the high-level overview of the infrastracture:

![iso-8583-overview](https://github.com/subclone/payment-processor/assets/88332432/939a8e5c-0b2e-4735-b0f4-003726008248)


## Notes

There are some important assumtions and notes you should be aware of before testing this PoC:

- that it is a PoC and should not be used in production
- chain relies on the trusted oracle and payment processor server and serves as the settlement/extension layer of the existing financial system
- single source of truth is the offchain ledger, for the sake of simplicity. In the future, it would be possible to implement a more complex system where the on-chain balances are more important.
- oracles are in a semi-trusted environment, i.e. they are trusted to sign transactions, but not to decide on the validity of the transactions. This is done by the payment processor.
- the payment processor is a trusted entity that is responsible for the finality of the transactions. It is PCIDSS compliant and is responsible for the security of the funds.

## Run the demo

For demonstration purposes, `docker-compose` configuration is provided. It will start the following services:
Expand All @@ -27,19 +38,20 @@ Then start the services:
docker-compose up
```

You will be able to access the demo merchant application at `http://0.0.0.0:3001`.
You will be able to access the demo merchant application at `http://0.0.0.0:3002`.

And assuming you are running the Substrate chain, you can access the explorer [here](https://polkadot.js.org/apps/?rpc=ws://localhost:9944#/explorer).

## Demo flow

Documentation of [merchant application](./interface/README.md) contains the details about the demo flow, you can follow it to fully test the setup. Note that, sometimes websocket connection with frontend is lost, so you might need to refresh the page.
Main demo walkthrough is located [here](./DEMO.md). It contains comprehensive information about the demo flow, interactions between the components and the user facing side of the infrastracture. It also provides step by step guide on how to test main features of the milestone.

## Notes

Some important notes about the project:

- It is a PoC implementation, so there are many places where we cut corners and some things are hard coded.
- ISO-8583:1987 standard is used.
- Substrate chain integration is not implemented yet.
- Unit tests are more like integration tests (somewhat similar to Substrate).

## Contents
Expand Down
64 changes: 64 additions & 0 deletions docker-compose.local.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
version: "3.8"

services:
postgres:
image: postgres:14.9-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
POSTGRES_HOST_AUTH_METHOD: trust
ports:
- 5433:5433
volumes:
- ./postgres-data:/var/lib/postgresql/data
restart: always
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
oracle:
build: ./pcidss
depends_on:
postgres:
condition: service_healthy
ports:
- 3030:3030
environment:
- RUST_LOG=debug
platform: linux/x86_64
command:
- --iso8583-spec=/usr/bin/spec.yaml
- --database-host=postgres
- --database-port=5433
- --ws-url=ws://host.docker.internal:9944
- --dev
links:
- postgres

interface:
build: ./interface
ports:
- 3002:3002
environment:
- GENERATE_SOURCEMAP=false
depends_on:
- oracle
- server

server:
build: ./payment-processor
environment:
- ORACLE_RPC_URL=ws://oracle:3030
ports:
- 3001:3001
depends_on:
postgres:
condition: service_healthy
oracle:
condition: service_started

volumes:
postgres-data:
driver: local
4 changes: 2 additions & 2 deletions interface/.dockerignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
node_modules
build
**/node_modules/
**/build/
10 changes: 5 additions & 5 deletions interface/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Use an official Node runtime as the base image
FROM node:18
FROM node:20

# Set the working directory in the container
WORKDIR /usr/src/app
Expand All @@ -12,7 +12,7 @@ RUN apt update -y && apt upgrade -y && \
COPY package.json yarn.lock ./

# Install the application's dependencies using yarn
RUN yarn install
RUN yarn global add node-gyp && yarn install --frozen-lockfile

# Copy the rest of the application's files into the container
COPY . .
Expand All @@ -21,7 +21,7 @@ COPY . .
RUN yarn run build

# Use a lightweight version of Node.js as a second stage build
FROM node:18-slim
FROM node:20-slim

WORKDIR /usr/src/app

Expand All @@ -34,7 +34,7 @@ ENV MODE="production"
RUN npm install -g serve

# Start the React application
CMD [ "serve", "-l", "tcp://0.0.0.0:3001", "-s", "build" ]
CMD [ "serve", "-l", "tcp://0.0.0.0:3002", "-s", "build" ]

# Expose port 5000 for the React app to be accessible outside the container
EXPOSE 3001
EXPOSE 3002
Loading
Loading