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

feat(copm): add Corda COPM implementation #3625

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

jenniferlianne
Copy link

Primary change:

Implements COPM primitives for Corda as a cacti plugin. The implementation follows the model of
the Corda ledger connector plugin, where a typescript pass-through implementation is registered on the plugin server, and commands are implemented on a separate grpc server in the Kotlin Spring framework.

Secondary changes:

  • The lock claim protobuf structure was updated to reduce the number of parameters.
  • A no-op endpoint was added, per project specification
  • The format of the inter-network command for requesting the status of a pledge varies by remote network type and asset. Adds a function to the typescript interop configuration interface to supply the appropriate command given the remote network and asset.
  • Adds test package to test combinations of network types
  • Updates CI script to use new testing framework
  • Updates linter ignore to include weaver build directories, allowing yarn lint to pass on a system where weaver libraries have been built. Also excludes docs directory to avoid linting minified js from documentation packages.

Pull Request Requirements

  • Rebased onto upstream/main branch and squashed into single commit to help maintainers review it more efficient and to avoid spaghetti git commit graphs that obfuscate which commit did exactly what change, when and, why.
  • Have git sign off at the end of commit message to avoid being marked red. You can add -s flag when using git commit command. You may refer to this link for more information.
  • Follow the Commit Linting specification. You may refer to this link for more information.

Character Limit

  • Pull Request Title and Commit Subject must not exceed 72 characters (including spaces and special characters).
  • Commit Message per line must not exceed 80 characters (including spaces and special characters).

A Must Read for Beginners
For rebasing and squashing, here's a must read guide for beginners.

Copy link
Contributor

@petermetz petermetz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jenniferlianne Looking pretty high quality in general, but as usual I have some requests. On top of the comments I left inline, please make sure to include a test case which verifies the plugin being functional while used through the API server (you'll most likely need a separate package because this one cannot depend on the API server due to circular dependency issues)
If you need examples just let me know.

@@ -0,0 +1 @@
{"O=PartyA, L=London, C=GB@Corda_Network":{"host":"127.0.0.1","username":"clientUser1","password":"test","port":10006},"O=PartyB, L=London, C=GB@Corda_Network":{"host":"127.0.0.1","username":"clientUser1","password":"test","port":10009},"O=PartyA, L=London, C=GB@Corda_Network2":{"host":"127.0.0.1","username":"clientUser1","password":"test","port":30006},"O=PartyB, L=London, C=GB@Corda_Network2":{"host":"127.0.0.1","username":"clientUser1","password":"test","port":30009}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jenniferlianne Is this something that has to be shipped to production or just a testing aritfact? If it's only for testing then I'd recommend placing it somewhere under src/test/json/resources or similar like src/test/json/fixtures/

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file has been moved to /src/test/json

packages/cacti-plugin-copm-corda/start-app.sh Outdated Show resolved Hide resolved
@jenniferlianne jenniferlianne force-pushed the copm_corda branch 6 times, most recently from e107eb5 to e04747c Compare November 14, 2024 13:21
Copy link
Contributor

@petermetz petermetz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jenniferlianne LGTM, thank you!

@jenniferlianne
Copy link
Author

@jenniferlianne Looking pretty high quality in general, but as usual I have some requests. On top of the comments I left inline, please make sure to include a test case which verifies the plugin being functional while used through the API server (you'll most likely need a separate package because this one cannot depend on the API server due to circular dependency issues) If you need examples just let me know.

As mentioned on the call, the plugin is brought up via the ApiServer in both fabric and corda cases. Please see:
packages/cacti-copm-test/src/main/typescript/corda/copm-tester-corda.ts line 118
packages/cacti-copm-test/src/main/typescript/fabric/copm-tester-fabric.ts line 122

@@ -0,0 +1,194 @@
WORKSPACE ?= $(shell realpath `pwd`/../../)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assuming this makefile is for starting the test networks and testing the copm end-to-end, as per structure of cacti, shouldn't this go to examples instead of packages?
@petermetz @VRamakrishna let me know if I make sense...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file can be moved to cacti-copm-test.

cacti-copm-test uses the weaver samples to do end-to-end testing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer it be moved to cacti-copm-test then. Let's completely separate the testing setup and logic from the generic components.

Ideally, I'd separate the test setups from the testing logic too, so that the testing logic could get a "spec" for the test setup and run generic tests on the network it's been given, but I think the Cacti package structure doesn't make this easy.

Moving this logic to the cacti-copm-test package seems to be the low-hanging-fruit option now, so let's do that. Perhaps later, we can refactor this to move the testnet launch logic to examples (as @sandeepnRES suggests), thereby making cacti-copm-test also oblivious to the network structure.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have moved all the Makefiles to cacti-copm-test. The Makefile_corda and Makefile_fabric files have 3 key targes: setup, lock-network, and pledge-network. These can be referenced either directly:

make -f Makefile_corda setup

or via wildcard targets in the main makefile:

make corda-setup

Future network types can follow this pattern.


export class WeaverInteropConfiguration implements CopmIF.InteropConfiguration {
private log: Logger;
private weaverRelativePath = "../../../../../../weaver/";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are hardcoded paths in this file, since this is for testing purpose, may be make it more configurable, instead of hardcoded values?
Also this is also why I believe this package should be in examples and not in packages directory...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see this in several places above (and probably below) too. Given that this is a test package, I suppose hardcoding these paths is OK for now. But I wonder if you can allow such values to be passed through constructors instead, with the hardcoded paths then being moved to the commands that start and run the tests. That will make the code base more maintainable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay yeah agree with Rama.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is an example implementation of an abstract interface, and not meant to be re-used. In addition to the hard-coded location of the weaver fabric-cli json settings (stored in a file), the class also contains hard-coded reference to the weaver contracts.

In general, I would advise against forcing use of a local json file for data storage. While it's nice for getting an example system going, it scales poorly and precludes other options that would be easier for end-users to maintain.

@@ -0,0 +1,119 @@
package com.copmCorda
Copy link
Contributor

@sandeepnRES sandeepnRES Nov 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this file is a sample? Asking because I don't see any hard coded values or anything specific to testnet.

Copy link
Contributor

@VRamakrishna VRamakrishna Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is in the sample subfolder within the Corda plugin folder. That said, it does look like the logic is generic, though the remoteCopmContracts variable seems specific to the asset exchange contracts.

}

override fun getPledgeInfoCmd(claim: ValidatedClaimPledgedAssetV1Request): DLTransactionParams {
return DLTransactionParams("com.cordaSimpleApplication.flow",
Copy link
Contributor

@sandeepnRES sandeepnRES Nov 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hardcoded value here, we should not refer sample application anywhere unless its a test-code. I'll suggest take it from parameters, or configurations.

Copy link
Contributor

@sandeepnRES sandeepnRES Nov 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I just saw that this is inside sample directory, so for every application someone needs to write code similar to these files? I'd prefer some config jsons/yaml instead of a kotlin code. But that's my preference, others can comment too if they are okay with it @VRamakrishna @petermetz

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. This is left up to the app for now (as opposed to json files) as in larger applications configuration info could be stored in, for instance, a database to make it easier to administer.

As I have mentioned elsewhere, I also think some of this application configuration could be pushed down to the contracts. As requested by @VRamakrishna , have a working draft where asset type registration is done in the interop contract: https://github.com/jenniferlianne/cacti/tree/copm_register_assets_in_chaincode

Copy link
Contributor

@sandeepnRES sandeepnRES Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay makes sense then.
Only thing is, if someone's application is to do remote call only once, they will have overhead to store everything in contract which will be useless after one call.

Its useful only if the remote transaction is used regularly.

}

override fun getPledgeInfoCmd(claim: ValidatedClaimPledgedAssetV1Request): DLTransactionParams {
return DLTransactionParams("com.cordaSimpleApplication.flow",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here... and below line 16 too

claim.sourceCert,
claim.destinationAccount.organization,
claim.destCert)
return DLTransactionParams("simpleassettransfer","GetTokenAssetPledgeStatus", params )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here too hardcoded...

}

override fun getPledgeInfoCmd(claim: ValidatedClaimPledgedAssetV1Request): DLTransactionParams {
return DLTransactionParams("simpleassettransfer",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here.

}

public getPackageName(): string {
return `@hyperledger-cacti/cacti-plugin-copm-corda`;
Copy link
Contributor

@sandeepnRES sandeepnRES Nov 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there a way to get this programmatically?
Because the prefix might change

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This follows the example of other cactus packages.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to get this from a configuration file or an environmental variable. Personally, I'd suggest that other Cactus packages do something similar too, @petermetz, rather than hardcode such values.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check if we can get it from package.json, I think that would be better.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed on the project channel, this is outside of the scope of the copm project.

setup: build-local-deps server-docker-image


pledge-network:
Copy link
Contributor

@sandeepnRES sandeepnRES Nov 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would suggest moving these makefile targets, like starting network and other components to tests, and those should ideally be not in packages I believe.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makefiles have been moved to cacti-copm-test and the cacti-plugin-copm-corda/src/test/kotlin directories.

@sandeepnRES
Copy link
Contributor

sandeepnRES commented Nov 19, 2024

@jenniferlianne Thank you for the PR, overall looks good to me. Just some small suggestions above I've shared.

jest.config.js Outdated
@@ -6,6 +6,7 @@ module.exports = {
moduleNameMapper: {
"^(\\.\\.?\\/.+)\\.jsx?$": "$1",
},
modulePathIgnorePatterns: ["./weaver/core/identity-management"],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This module does get exercised in Weaver transaction pipelines, though currently only the iin-agent subfolder (other subfolders are placeholders for mechanisms that are specified in the Weaver RFCs but haven't been implemented yet).

Is this module causing any issues that necessitates its exclusion?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is specific to the jest testing system, and there are no jest tests in weaver. The weaver convention of copying packages when building causes collisions in the haste map, so jest tests are unable to run. In my branch where I am building the dependencies as part of running the test, I have had to make additional exceptions.

make convert-compose-method2 && \
make start-server COMPOSE_ARG='--env-file docker/testnet-envs/.env.n2'

# IIN --------------------------------------------------------------------------------------
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sandeepnRES I think we don't need the iin agents for scenarios involving Corda, right? They won't do anything useful.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jenniferlianne Is this used for Fabric-Fabric testing too, or just ones that involve Corda networks?

Copy link
Author

@jenniferlianne jenniferlianne Nov 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is used for testing all combinations. I have reorganized the Makefiles into cacti-copm-test.

}
},
"operationId": "noopV1",
"summary": "A no-op operation. May be used as a heath check",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"heath" --> "health"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected.

"source_certificate",
"hash_info"
],
"required": ["lock_id", "destination", "asset", "hash_info"],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove source (or source_certificate)?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the lock claim for the fabric NFT case to use the lock id instead of the asset agreement to claim the lock, to be consistent with the Corda implementation. After making this change you don't need information about source any more.

"post": {
"x-hyperledger-cacti": {
"http": {
"path": "/api/v1/plugins/@hyperledger/cacti-plugin-copm/no-op",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change @hyperledger --> @hyperledger-cacti here and in other locations.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@@ -15,7 +16,8 @@ export type CopmContractNames = {
};

export type RemoteNetworkConfig = {
channelName: string;
channelName: string; // fabric-specific
chaincode: string; // fabric-specific
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename this to chaincodeName.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably networkName instead of network in the below line 21?

Copy link
Author

@jenniferlianne jenniferlianne Nov 25, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After further discussion on the project channel I have removed the chaincode and flowPackage variables from the remote network configuration struct as remote networks may use multiple chaincode packages in both fabric and corda. The network variable has been renamed networkName.

"author": {
"name": "Hyperledger Cacti Contributors",
"email": "[email protected]",
"url": "https://www.hyperledger.org/use/cacti"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This URL now automatically redirects to https://www.lfdecentralizedtrust.org/projects/cacti, so perhaps you can change it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been updated.

}

public networkNames(): string[] {
return ["Corda_Network", "Corda_Network2"];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if this should be hardcoded or lifted from a configuration file. @sandeepnRES ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the user identities and org names are also hardcoded below. I looked at the older code, where such values were hardcoded in the test folders of the corda-interop-app module, so if this package is the equivalent of that test suite, then I'm fine with the hardcoding.

cp $(WORKSPACE)/weaver/core/network/corda-interop-app/interop-workflows/build/libs/interop-workflows-*.jar localdeps
cp $(WORKSPACE)/weaver/core/network/corda-interop-app/interop-contracts/build/libs/interop-contracts-*.jar localdeps
cp $(WORKSPACE)/weaver/samples/corda/corda-simple-application/contracts-kotlin/build/libs/contracts-kotlin-*.jar localdeps
cp $(WORKSPACE)/weaver/samples/corda/corda-simple-application/workflows-kotlin/build/libs/workflows-kotlin-*.jar localdeps
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can understand the rest, but why do you need weaver/samples/... as dependencies?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current corda interop chaincode require passing down the asset-specific CommandData instances for issue and burn, as well as getting the pledgeId. This is something that could be avoided with asset type registration.

Here are the asset-specific commands being passed to the chaincode in the corda CLI:

"@hyperledger-cacti/cacti-copm-core": "2.0.0",
"@hyperledger-cacti/cacti-copm-test": "2.0.0",
"@hyperledger/cacti-weaver-protos-js": "2.0.0",
"@hyperledger/cacti-weaver-sdk-fabric": "2.0.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2.0.0 version doesn't exist for the two packages above. Because of the organization change, the last version tagged under @hyperledger was [2.0.0-rc.7](https://github.com/orgs/hyperledger/packages/container/cacti-weaver-driver-fabric/283162801?tag=2.0.0-rc.7). Weaver publish actions failed during the 2.0.0 release because paths were not updated. These actions should succeed when the next release (2.0.1) is done, hopefully in the next few days. So you have two options: (1) wait for the next release and then update these version numbers here and elsewhere in your code, or (2) use the last release version 2.0.0-rc.7.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These refer to the local monorepo versions, which is why they are able to compile. The packages are built in the cactus way, with npm run configure at the top level. This uses the tsconfig file at at the root level which builds the packages in a specific order and keeps a reference of local packages. One of the challenges of this project was getting everything to build successfully given the differences in build philosophy between cactus and weaver.

@jenniferlianne jenniferlianne force-pushed the copm_corda branch 11 times, most recently from f9859fc to ac09efd Compare November 25, 2024 21:27
Primary change:

Implements COPM primitives for Corda as a cacti
plugin.  The implementation follows the model of
the Corda ledger connector plugin, where a
typescript pass-through implementation is
registered on the plugin server, and commands are
implemented on a separate grpc server in the
Kotlin Spring framework.

Secondary changes:

- The lock claim protobuf structure was updated
to reduce the number of parameters.
- A no-op endpoint was added, per project
specification
- The format of the inter-network command for
requesting the status of a pledge varies by
remote network type and asset.  Adds a function to
the typescript interop configuration  interface to
supply the appropriate command given
the remote network and asset.
- Adds test package to test combinations of
network types
- Updates CI script to use new testing
framework
- Updates linter ignore to include weaver build
directories, allowing yarn lint to pass on
a system where weaver libraries have been built.
Also excludes docs directory to avoid linting
minified js from documentation packages.

Signed-off-by: Jennifer Bell <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants