Skip to content

Commit

Permalink
feat(bungee-hermes): process & merge views
Browse files Browse the repository at this point in the history
- Added new types for view merging
- Created some merge and process policies for demonstration
- new endpoints and plugin logic to merge and process views
- two new tests to test new functionality
- utility function to fully deserialize a view
- slightly changed View type, to keep reccord of its old versions metadata
- updated README.md

Signed-off-by: eduv09 <[email protected]>
  • Loading branch information
eduv09 authored and petermetz committed May 16, 2024
1 parent 69c9bf3 commit 231a5e5
Show file tree
Hide file tree
Showing 18 changed files with 2,091 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ export class JsObjectSigner {
* @param data
* @returns {string}
*/
private dataHash(data: unknown): string {
public dataHash(data: unknown): string {
const hashObj = new sha3.SHA3Hash(256);
hashObj.update(stringify(data));
const hashMsg = hashObj.digest(`hex`);
Expand Down
55 changes: 47 additions & 8 deletions packages/cactus-plugin-bungee-hermes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ Endpoints exposed:
- GetPublicKey
- GetAvailableStrategies
- VerifyMerkleRoot
- MergeViewsV1
- ProcessViewV1


## Running the tests
Expand All @@ -80,7 +82,9 @@ Endpoints exposed:
- **fabric-test-basic.test.ts**: A test using strategy-fabric and a fabric connector, testing creating views for different timeframes and states.
- **besu-test-pruning.test.ts**: A test using strategy-besu and a besu connector, testing creating views for specific timeframes.
- **fabric-test-pruning.test.ts**: A test using strategy-fabric and a fabric connector, testing creating views for specific timeframes.
- **bungee-api-test.test.ts**: A more complex test, using both besu and fabric strategies, fabric and besu connectors, and calls to bungee-hermes API. Tests bungee's API and functionality with multiple strategies.
- **bungee-api-test.test.ts**: A more complex test, using multiple strategies, connectors, and calls to bungee-hermes API. Tests new functionalities like view proof validation.
- **bungee-merge-views.test.ts**: A test using besu-strategy and connector, to demonstrate and test the mergeView functionality of bungee-hermes.
- **bungee-process-views.test.ts**: A test using besu-strategy and connector, to demonstrate and test processView functionality of the plugin.

Tests developed using JEST testing framework.

Expand Down Expand Up @@ -152,8 +156,26 @@ Note that each strategy can be used to query different ledgers (ledgers of the s
Each strategy implements the logic to query information from each different ledger (i.e. capture set of asset states), while bungee-hermes plugin handles the snapshot and view creation.


'View' object contains a 'viewProof'. viewProof is composed by two merkle trees, one for stateProofs and another for transactionProofs.
One can check if the content of a view has no inconsistencies, by querying the VerifyMerkleRoot endpoint with the appropriate input:
We can merge views to create an IntegratedView. Integrated views are the result of merging multiple views, with or without using a privacy policy.
IntegratedViews have a map of ExtendedStates (stateId -> ExtendedState). And ExtendedState is the data gathered for a specific stateId, from different views map(viewId -> State).

Example:
```typescript
const mergeViewsNoPolicyReq = await bungeeApi.mergeViewsV1({
//for previously obtained views
serializedViews: [JSON.stringify(view.view), JSON.stringify(view2.view)],
//no policy. When policy is requested, take note that order of arguments matter
mergePolicy: undefined,
policyArguments: [],
});
expect(mergeViewsNoPolicyReq.status).toBe(200);
expect(mergeViewsNoPolicyReq.data.integratedView).toBeTruthy();
expect(mergeViewsNoPolicyReq.data.signature).toBeTruthy();
```


'View' object contains a 'viewProof'. 'viewProof' is composed by two merkle trees, one for 'stateProofs' and another for 'transactionProofs'. The analogous exists for IntegratedView objects, a merkle tree is created for all transactions and states in the IntegratedView.
One can check if the content of a view or integratedView has no inconsistencies, by querying the VerifyMerkleRoot endpoint with the appropriate input:

```typescript
//using a previously created View object
Expand All @@ -162,10 +184,9 @@ One can check if the content of a view has no inconsistencies, by querying the V
.getStateBins()
.map((x) => JSON.stringify(x.getStateProof()));
const transactionProofs: string[] = [];
view?
.getAllTransactions()
.forEach((t) => transactionProofs.push(JSON.stringify(t.getProof())));

view?.getAllTransactions()
.forEach((t) => transactionProofs.push(JSON.stringify(t.getProof()))),
);
const verifyStateRoot = await bungeeApi.verifyMerkleRoot({
input: stateProofs?.reverse(), //check integrity, order should not matter
root: proof?.statesMerkleRoot,
Expand All @@ -179,12 +200,30 @@ One can check if the content of a view has no inconsistencies, by querying the V
expect(verifyTransactionsRoot.data.result).toBeTrue();
```

Lastly, we can also process views according to a privacy-policy as follows:

```typescript
import { hideState } from "../../../main/typescript/view-creation/privacy-policies";

bungee.addViewPrivacyPolicy("policy1", hideState);

const processed = await bungeeApi.processViewV1({
serializedView: JSON.stringify({
view: JSON.stringify(view.view as View),
signature: view.signature,
}),
policyId: "hideState",
policyArguments: [BESU_ASSET_ID],
});
```
This example uses the hideState policy, which takes as arguments a stateId to remove from the new view.
When we apply a policy, the old view metadata is stored in the new View for traceability. This process can be applied multiple times


## 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.
Please review [CONTRIBUTING.md](https://github.com/hyperledger/cactus/blob/main/CONTRIBUTING.md "CONTRIBUTING.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.
162 changes: 161 additions & 1 deletion packages/cactus-plugin-bungee-hermes/src/main/json/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@
},
"components": {
"schemas": {
"PrivacyPolicyOpts":{
"description": "identifier of the policy used to process a view",
"type": "string",
"enum": ["pruneState"],
"x-enum-varnames":["PruneState"]
},
"MergePolicyOpts":{
"description": "identifier of the policy used to merge views (can be none)",
"type": "string",
"enum": ["pruneState", "pruneStateFromView", "NONE"],
"x-enum-varnames":["PruneState", "PruneStateFromView", "NONE"]
},
"CreateViewRequest":{
"type":"object",
"description": "Request object for createViewV1 endpoint",
Expand Down Expand Up @@ -80,7 +92,7 @@
},
"CreateViewResponse":{
"type":"object",
"description": "This is the response for a viewRequests",
"description": "This is the response for a CreateViewRequest or ProcessViewRequest",
"properties": {
"view":{
"type":"string",
Expand Down Expand Up @@ -138,6 +150,72 @@
"example": "true"
}
}
},
"MergeViewsResponse":{
"type":"object",
"description": "This is the response of a mergeViewRequest",
"properties": {
"integratedView":{
"type":"string",
"example": "Object"
},
"signature":{
"type": "string",
"example": "signature of Object"
}
},
"example": {"integratedView": "Object", "signature":"signature of Object"}
},
"MergeViewsRequest":{
"type":"object",
"description": "This is the input for a mergeViewRequest",
"required": ["serializedViews", "mergePolicy"],
"properties": {
"serializedViews":{
"nullable": false,
"type":"array",
"description": "Array of serialized views",
"items":{
"type": "string",
"nullable": false,
"example": "View object stringified"
}
},
"mergePolicy":{
"$ref" : "#/components/schemas/MergePolicyOpts"
},
"policyArguments":{
"type": "array",
"description": "Arguments for the privacy policy function. Order is important",
"items":{
"type": "string"
}
}
},
"example": {"serializedViews": ["View 1", "View2"], "mergePolicy": "undefined" }
},
"ProcessViewRequest":{
"type":"object",
"description": "This is the input for a mergeViewRequest",
"required": ["serializedView", "policyId", "policyArguments"],
"properties": {
"serializedView":{
"type": "string",
"nullable": false,
"example": "View object stringified"
},
"policyId":{
"$ref" : "#/components/schemas/PrivacyPolicyOpts"
},
"policyArguments":{
"type": "array",
"description": "Arguments for the privacy policy function. Order is important",
"items":{
"type": "string"
}
}
},
"example": {"serializedView": "View 1", "policyId": "policy 1", "policyArguments": ["stateId"]}
}
}
},
Expand Down Expand Up @@ -286,6 +364,88 @@
}
}
}
},
"/api/v1/plugins/@hyperledger/cactus-plugin-bungee-hermes/merge-views": {
"get": {
"x-hyperledger-cacti": {
"http": {
"verbLowerCase": "get",
"path": "/api/v1/plugins/@hyperledger/cactus-plugin-bungee-hermes/merge-views"
}
},
"operationId": "mergeViewsV1",
"summary": "Merges multiple views according to a privacy policy",
"description": "",
"parameters": [],
"requestBody": {
"required": true,
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MergeViewsRequest"
}
}
}
},
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MergeViewsResponse"
}
}
}
},
"404": {
"description": "Could not complete request."
}
}
}
},
"/api/v1/plugins/@hyperledger/cactus-plugin-bungee-hermes/process-view": {
"get": {
"x-hyperledger-cacti": {
"http": {
"verbLowerCase": "get",
"path": "/api/v1/plugins/@hyperledger/cactus-plugin-bungee-hermes/process-view"
}
},
"operationId": "processViewV1",
"summary": "Creates a Blockchain View.",
"description": "",
"parameters": [],
"requestBody": {
"required": true,
"description": "",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ProcessViewRequest"
}
}
}
},
"responses": {
"200": {
"description": "OK",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/CreateViewResponse"
},
"example": {"view": "Object", "signature":"signature of Object"}
}
}
},
"404": {
"description": "Could not complete request."
}
}
}
}

}
}
Loading

0 comments on commit 231a5e5

Please sign in to comment.