Skip to content

Commit

Permalink
refactor(cc-tx-visualization): capture transactional data with RxJS
Browse files Browse the repository at this point in the history
The plugin now utilizes RxJS instead of RabbitMQ in transaction monitoring.
ReplaySubjects store and emit observed transactional data to subscribers.

fix(cc-tx-visualization): rebase latest version

Signed-off-by: Rafael Belchior <rafael.belchior@tecnico.ulisboa.pt>

squash! - migrate a test case to Fabric v2.5.6 LTS AIO

This is just a snippet of a change from the pair programming
call with Bruno, it can be safely squashed, no worries.

Signed-off-by: Peter Somogyvari <peter.somogyvari@accenture.com>
Signed-off-by: Bruno Mateus <brumat315@gmail.com>
  • Loading branch information
brunoffmateus committed Apr 16, 2024
1 parent 079e787 commit 4bd50b7
Show file tree
Hide file tree
Showing 50 changed files with 3,461 additions and 2,064 deletions.
2 changes: 0 additions & 2 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@
"qscc",
"recoverupdateackmessage",
"rogpeppe",
"rabbitmq",
"RUSTC",
"Rwset",
"satp",
Expand Down Expand Up @@ -184,7 +183,6 @@
"unixfs",
"Unmarshal",
"uuidv",
"Visualizable",
"vscc",
"vuln",
"wasm",
Expand Down
4 changes: 0 additions & 4 deletions jest.config.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 0 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,22 +70,6 @@
"build:dev:frontend": "lerna run build:dev:frontend --scope='@hyperledger/cactus-example-*-frontend' --scope='@hyperledger/cacti-ledger-browser'",
"build:dev:common": "lerna exec --stream --scope '*/*common' -- 'del-cli dist/** && tsc --project ./tsconfig.json && webpack --env=dev --target=node --config ../../webpack.config.js'",
"build:dev:backend:postbuild": "lerna run build:dev:backend:postbuild",
"test:cmd-api-server": "tap --ts --timeout=600 \"packages/cactus-*cmd-api-server/src/test/typescript/{unit,integration}/\"",
"test:plugin-ledger-connector-besu": "tap --ts --jobs=1 --timeout=60 \"packages/cactus-*-besu/src/test/typescript/{unit,integration}/\"",
"test:plugin-htlc-besu-erc20": "tap --jobs=1 --timeout=600 \"packages/*htlc-eth-besu-erc20/src/test/typescript/{unit,integration}/\"",
"test:plugin": "tap --jobs=1 --timeout=600 \"packages/*test-plugin-htlc-eth-besu/src/test/typescript/{unit,integration}/\"",
"test:plugin-ledger-connector-quorum": "tap --ts --jobs=1 --timeout=60 \"packages/cactus-*-quorum/src/test/typescript/{unit,integration}/\"",
"test:cctxviz": "tap --jobs=1 --timeout=600 \"packages/cactus-plugin-cc-tx-visualization/src/test/typescript/{unit,integration}/\"",

"test:plugin-ledger-connector-iroha": "tap --ts --jobs=1 --timeout=600 \"packages/cactus-*-iroha/src/test/typescript/{unit,integration}/\"",
"test:plugin-htlc-besu": "tap --jobs=1 --timeout=600 \"packages/*htlc-eth-besu/src/test/typescript/{integration}/\"",
"build:dev:plugin-consortium-manual": "lerna exec --stream --scope '*/*manual-consortium' -- 'del-cli dist/** && tsc --project ./tsconfig.json && webpack --env=dev --target=node --config ../../webpack.config.js'",
"build:dev:plugin-cc-tx-visualization": "lerna exec --stream --scope '*/*cc-tx-visualization' -- 'del-cli dist/** && tsc --project ./tsconfig.json && webpack --env=dev --target=node --config ../../webpack.config.js'",
"build:dev:example-supply-chain-backend": "lerna exec --stream --scope '*/*example-supply-chain-b*' -- 'del-cli dist/** && tsc --project ./tsconfig.json && webpack --display-modules --env=dev --target=node --config ../../webpack.config.js'",
"build:dev:example-carbon-accounting-backend": "lerna exec --stream --scope '*/*carbon-accounting-b*' -- 'del-cli dist/** && tsc --project ./tsconfig.json && webpack --display-modules --env=dev --target=node --config ../../webpack.config.js' && cp -r examples/cactus-example-carbon-accounting-backend/src/utility-emissions-channel/ examples/cactus-example-carbon-accounting-backend/dist/lib/",
"build:dev:sdk": "lerna exec --stream --scope '*/*sdk' -- 'del-cli dist/** && tsc --project ./tsconfig.json && webpack --env=dev --target=node --config ../../webpack.config.js'",
"build:dev:plugin-ledger-connector-corda": "lerna exec --stream --scope '*/*connector-corda' -- 'del-cli dist/** && npm run tsc && webpack --env=dev --target=node --config ../../webpack.config.js'",
"test:plugin-ledger-connector-corda": "tap --ts --jobs=1 --timeout=600 \"packages/cactus-*-corda/src/test/typescript/{unit,integration}/\"",
"webpack": "lerna run webpack:dev",
"webpack:dev:web": "lerna run webpack:dev:web",
"webpack:dev:node": "lerna run webpack:dev:node",
Expand Down
1 change: 1 addition & 0 deletions packages/cactus-plugin-cc-tx-visualization/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
cactus-openapi-spec-plugin-consortium-manual.json
src/main/typescript/generated/openapi/typescript-axios/.npmignore
src/test/csv
src/test/json
src/test/test-results/*.out
119 changes: 117 additions & 2 deletions packages/cactus-plugin-cc-tx-visualization/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,118 @@
# `@hyperledger/cactus-plugin-cctxviz`
# `@hyperledger/cactus-plugin-cc-tx-visualization`

The proposed plugin allows generating process models from arbitrary cross-chain use cases. Currently supports Fabric and Besu. More documentation to come soon.
The package provides `Hyperledger Cacti` a way to generate process models from arbitrary cross-chain use cases. The implementation follows the paper [Hephaestus](https://www.techrxiv.org/doi/full/10.36227/techrxiv.20718058.v3).

With this plugin it will be possible to generate cross-chain models from local transactions in different ledgers (currently supports Fabric and Besu), realizing arbitrary cross-chain use cases and allowing operators to monitor their applications.
Through monitoring, errors like outliers and malicious behavior can be identified, which can enable programmatically stopping attacks (circuit breaker), including bridge hacks.

## Summary

- [`@hyperledger/cactus-plugin-cc-tx-visualization`](#hyperledgercactus-plugin-cc-tx-visualization)
- [Summary](#summary)
- [Getting Started](#getting-started)
- [Prerequisites](#prerequisites)
- [Architecture](#architecture)
- [RxJS Transaction Monitoring](#rxjs-transaction-monitoring)
- [Cross-Chain Model Pipeline](#cross-chain-model-pipeline)
- [Running the tests](#running-the-tests)
- [Usage](#usage)
- [Contributing](#contributing)
- [License](#license)


## Getting Started

Clone the git repository on your local machine. Follow these instructions that will get you a copy of the project up and running on your local machine for development and testing purposes.

### Prerequisites

In the root of the project to install the dependencies execute the command:
```sh
npm run configure
```

Know how to use the following plugins of the project:

- [cactus-plugin-ledger-connector-fabric](https://github.com/hyperledger/cactus/tree/main/packages/cactus-plugin-ledger-connector-fabric)
- [cactus-plugin-ledger-connector-besu](https://github.com/hyperledger/cactus/tree/main/packages/cactus-plugin-ledger-connector-besu)


## Architecture

### RxJS Transaction Monitoring

This plugin utilizes RxJS (Reactive Extensions for JavaScript) to monitor transactions issued in Hyperledger Besu and Hyperledger Fabric connectors.

RxJS provides a powerful framework for asynchronous or callback-based code, each connector maintains an RxJS `ReplaySubject`, named `txSubject`, which acts as a message bus for emitting transaction data.

- When a transaction is issued in a connector, the `ReplaySubject` stores the value it observes in an internal buffer. This observation is achieved by passing the value to its `next` method.
- When a new subscriber subscribes to the `txSubject`, it synchronously emits all values in its buffer in a First-In-First-Out (FIFO) manner. This ensures that subscribers receive the most recent transactional data, regardless of when they subscribe.
- The transactional data emitted includes essential information such as the transaction ID, timestamp, and other parameters, which are necessary for creating transaction receipts within the plugin.

### Cross-Chain Model Pipeline

The plugin employs a structured pipeline to create a cross-chain model from monitored connector transactions:

1. **Transaction Emission**: Connectors issue local transactions against their respective target blockchains. Each transaction's data is emitted by the `txSubject` to the subscribers within our plugin.

2. **Receipt Polling**: Upon receiving of transactional data, the plugin processes it into transaction receipts. This step involves precessing transactional information received such as transaction IDs, timestamps, and other parameters.

3. **Cross-Chain Event Logging**: The processed transaction receipts can then be used to create cross-chain events, forming a cross-chain event log.

4. **Cross-Chain Model Updating**: The plugin parses the cross chain event log and updates the cross chain model with the new information received from the connectors.

## Running the tests
- **api-surface.test.ts**: Verifies the successful loading of the library.
- **cctxviz-basic-test.test.ts**: Conducts the simulation of a transaction without instantiating the connectors, and tests that the plugin monitors, captures, and processes the transactional data and creates a cross-chain event.
- **cctxviz-persist-cross-chain-log.test.ts**: Tests the plugin's ability to export transactional data, in both CSV and JSON formats, as cross-chain event logs.
- **cctxviz-generate-use-case-dummy-baseline-events.test.ts**: Conducts a simulation of a series of transactions, exporting the cross-chain event log in CSV and JSON formats, and tests if the cross-chain model is correctly saved.
- **cctxviz-generate-use-case-dummy-invalid.test.ts**: Tests a simulation of a series of transactions across multiple cases.
- **initialize-cctxviz-usecase-fabric-besu-6-events.test.ts**: Tests the plugin's ability to effectively monitor, capture, and process transactional data emitted from the RxJS ReplaySubjects in the Fabric and Besu connectors.

## Usage
Let us consider two conectors: one connected to Hyperledger Besu and one connected to Hyperledger Fabric. To monitor cross-chain transactions and create a cross-chain model we should follow the next steps.

After instantiating the connectors, we instantiate the plugin as follows:
```typescript
let cctxvizOptions: IPluginCcTxVisualizationOptions;
cctxvizOptions = {
instanceId: randomUUID(),
logLevel: logLevel,
besuTxObservable: besuConnector.getTxSubjectObservable(),
fabricTxObservable: fabricConnector.getTxSubjectObservable(),
};
cctxViz = new CcTxVisualization(cctxvizOptions);
```

We set the desired caseID and start monitoring and processing the transactions into transaction receipts:

```typescript
cctxViz.setCaseId("Desired_CaseID");
cctxViz.monitorTransactions();
```

We can create cross-chain events from processed transaction receipts and add them to the cross-chain event log:

```typescript
await cctxViz.txReceiptToCrossChainEventLogEntry();
```

We can export the cross-chain event log to CSV and JSON files:

```typescript
await cctxViz.persistCrossChainLogCsv("output-file-CSV");
await cctxViz.persistCrossChainLogJson("output-file-JSON");
```

And we can update the cross-chain model with the events created from the transactional data captured:
```typescript
await cctxViz.aggregateCcTx();
```

## Contributing
We welcome contributions to Hyperledger Cactus in many forms, and there’s always plenty to do!

Please review [CONTIRBUTING.md](https://github.com/hyperledger/cactus/blob/main/CONTRIBUTING.md "CONTIRBUTING.md") to get started.

## License
This distribution is published under the Apache License Version 2.0 found in the [LICENSE ](https://github.com/hyperledger/cactus/blob/main/LICENSE "LICENSE ")file.
101 changes: 55 additions & 46 deletions packages/cactus-plugin-cc-tx-visualization/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,22 @@
"name": "@hyperledger/cactus-plugin-cc-tx-visualization",
"version": "1.0.0",
"description": "A web service plugin that provides management capabilities on cross-chain transactions visualization.",
"main": "dist/lib/main/typescript/index.js",
"mainMinified": "dist/cactus-plugin-cc-tx-visualization.node.umd.min.js",
"browser": "dist/cactus-plugin-cc-tx-visualization.web.umd.js",
"browserMinified": "dist/cactus-plugin-cc-tx-visualization.web.umd.min.js",
"module": "dist/lib/main/typescript/index.js",
"types": "dist/types/main/typescript/index.d.ts",
"files": [
"dist/*"
],
"scripts": {
"watch": "npm-watch",
"webpack": "npm-run-all webpack:dev webpack:prod",
"webpack:dev": "npm-run-all webpack:dev:node webpack:dev:web",
"webpack:dev:web": "webpack --env=dev --target=web --config ../../webpack.config.js",
"webpack:dev:node": "webpack --env=dev --target=node --config ../../webpack.config.js",
"webpack:prod": "npm-run-all webpack:prod:node webpack:prod:web",
"webpack:prod:web": "webpack --env=prod --target=web --config ../../webpack.config.js",
"webpack:prod:node": "webpack --env=prod --target=node --config ../../webpack.config.js"
},
"publishConfig": {
"access": "public"
},
"engines": {
"node": ">=10",
"npm": ">=6"
},
"repository": {
"type": "git",
"url": "git+https://github.com/hyperledger/cactus.git"
},
"keywords": [
"Hyperledger",
"Cactus",
"Integration",
"Blockchain",
"Distributed Ledger Technology"
],
"homepage": "https://github.com/hyperledger/cactus#readme",
"bugs": {
"url": "https://github.com/hyperledger/cactus/issues"
},
"repository": {
"type": "git",
"url": "git+https://github.com/hyperledger/cactus.git"
},
"license": "Apache-2.0",
"author": {
"name": "Hyperledger Cactus Contributors",
"email": "cactus@lists.hyperledger.org",
Expand All @@ -58,35 +37,65 @@
},
{
"name": "Rafael Belchior"
},
{
"name": "Bruno Mateus"
}
],
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/hyperledger/cactus/issues"
"main": "dist/lib/main/typescript/index.js",
"module": "dist/lib/main/typescript/index.js",
"browser": "dist/cactus-plugin-cc-tx-visualization.web.umd.js",
"types": "dist/types/main/typescript/index.d.ts",
"files": [
"dist/*"
],
"scripts": {
"build": "npm run tsc",
"tsc": "tsc --project ./tsconfig.json",
"watch": "npm-watch",
"webpack": "npm-run-all webpack:dev webpack:prod",
"webpack:dev": "npm-run-all webpack:dev:node webpack:dev:web",
"webpack:dev:web": "webpack --env=dev --target=web --config ../../webpack.config.js",
"webpack:dev:node": "webpack --env=dev --target=node --config ../../webpack.config.js",
"webpack:prod": "npm-run-all webpack:prod:node webpack:prod:web",
"webpack:prod:web": "webpack --env=prod --target=web --config ../../webpack.config.js",
"webpack:prod:node": "webpack --env=prod --target=node --config ../../webpack.config.js"
},
"homepage": "https://github.com/hyperledger/cactus#readme",
"dependencies": {
"@hyperledger/cactus-common": "1.0.0",
"@hyperledger/cactus-core": "1.0.0",
"@hyperledger/cactus-core-api": "1.0.0",
"@hyperledger/cactus-plugin-ledger-connector-fabric": "1.0.0",
"@hyperledger/cactus-plugin-ledger-connector-besu": "1.0.0",
"@hyperledger/cactus-common": "2.0.0-alpha.2",
"@hyperledger/cactus-core": "2.0.0-alpha.2",
"@hyperledger/cactus-core-api": "2.0.0-alpha.2",
"@hyperledger/cactus-plugin-ledger-connector-besu": "2.0.0-alpha.2",
"@hyperledger/cactus-plugin-ledger-connector-fabric": "2.0.0-alpha.2",
"@types/csv-stringify": "^3.1.0",
"amqp-ts": "1.8.0",
"axios": "0.21.1",
"axios": "0.21.4",
"body-parser": "1.19.0",
"csv-stringify": "6.0.5",
"express": "4.17.1",
"fabric-contract-api": "2.2.3",
"jose": "1.28.1",
"json-stable-stringify": "1.0.1",
"prom-client": "13.0.0",
"run-time-error-cjs": "1.4.0",
"socket.io-client-fixed-types": "4.5.4",
"typescript-optional": "2.0.1",
"uuid": "8.3.2"
"uuid": "8.3.2",
"web3": "1.6.1"
},
"devDependencies": {
"@hyperledger/cactus-test-tooling": "1.0.0",
"@hyperledger/cactus-plugin-keychain-memory": "2.0.0-alpha.2",
"@hyperledger/cactus-test-tooling": "2.0.0-alpha.2",
"@types/express": "4.17.8",
"@types/json-stable-stringify": "1.0.32",
"@types/uuid": "8.3.0"
}
"@types/uuid": "8.3.0",
"fabric-network": "2.2.20"
},
"engines": {
"node": ">=10",
"npm": ">=6"
},
"publishConfig": {
"access": "public"
},
"browserMinified": "dist/cactus-plugin-cc-tx-visualization.web.umd.min.js",
"mainMinified": "dist/cactus-plugin-cc-tx-visualization.node.umd.min.js"
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export type CrossChainEvent = {
caseID: string;
receiptID: string;
timestamp: Date;
timestamp: string;
blockchainID: string;
invocationType: string;
methodName: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import { LedgerType } from "@hyperledger/cactus-core-api";
import { Web3SigningCredential } from "@hyperledger/cactus-plugin-ledger-connector-besu/src/main/typescript/public-api";
import {
FabricSigningCredential,
GatewayOptions,
TransactReceiptBlockMetaData,
TransactReceiptTransactionCreator,
} from "@hyperledger/cactus-plugin-ledger-connector-fabric/src/main/typescript/generated/openapi/typescript-axios/api";
import { FabricSigningCredential } from "@hyperledger/cactus-plugin-ledger-connector-fabric";

export interface TransactionReceipt {
caseID: string;
Expand All @@ -16,53 +10,24 @@ export interface TransactionReceipt {
timestamp: Date;
}

export interface IsVisualizable {
// list of transaction receipts, that will be sent to cc-tx-viz
collectTransactionReceipts: boolean;
}

// TODO define Tx Receipt for Fabric
export interface FabricV2TxReceipt extends TransactionReceipt {
channelName: string;
transactionID: string | undefined;
contractName: string;
endorsingPeers?: string[];
endorsingParties?: string[];
transientData?: any | null;
gatewayOptions?: GatewayOptions;
signingCredentials: FabricSigningCredential;
blockNumber?: string;
transactionCreator?: TransactReceiptTransactionCreator;
blockMetaData?: TransactReceiptBlockMetaData;
chainCodeName?: string;
chainCodeVersion?: string;
responseStatus?: string;
cost?: number;
}

export interface BesuV2TxReceipt extends TransactionReceipt {
status: boolean;
transactionHash: string;
transactionIndex: number;
blockNumber: number;
blockHash: string;
contractName: string;
contractAddress?: string;
contractAbi?: string[];
value?: number | string;
gas?: number | string;
gasPrice?: number | string;
gasUsed?: number | string;
cumulativeGasUsed?: number | string;
transactionID: string;
gasUsed: number | string;
from: string;
to: string;
signingCredentials?: Web3SigningCredential;
keychainID?: string;
privateTransactionConfig?: string[];
timeoutMs?: number | string;
}

export function toSeconds(date: number): number {
return Math.floor(date / 1000);
}

export function millisecondsLatency(date: Date): number {
return new Date().getTime() - date.getTime();
}

0 comments on commit 4bd50b7

Please sign in to comment.