hyperledger / firefly-cli

FireFly Command Line Interface (CLI)
Apache License 2.0
56 stars 50 forks source link

Support quorum tessera blockchain node #310

Open rodion-lim-partior opened 2 weeks ago

rodion-lim-partior commented 2 weeks ago

This PR is raised to add Quorum and Tessera support for firefly-cli. We would like to ease the creation of a development environment for networks using the combination of Blockchain and Private Manager mentioned, and in future, build capabilities in Firefly stack such as extending the blockchain connector to cater for additional functionalities exposed by the combination.

This section describes some of the functionalities implemented from both an external and internal command line perspective:

External ff command line perspective Unsupported combinations / algorithms will be explicitly disabled on the command line flags.

Supported Consensus Mechanism (only when Quorum is selected)

Unsupported Consensus Mechanism (only when Quorum is selected)

Supported Client Combinations

Unsupported Client Combinations

Internal ff command line perspective

  1. There are many dependencies to spin up a Quorum/Tessera pair, one example is Quorum having to wait for Tessera to be in a ready state before starting up, we implemented separate docker entrypoint scripts to handle these dependencies for both Quorum and Tessera instead of passing docker args to the binary, so that it is easier to extend more complicated configurations in future. These entry point scripts are copied into the docker volumes during the first time setup
  2. To spin up a Tessera instance, we need to generate a private/public key pair. When sending private transactions, Quorum/Third party client needs to use the Tessera public key as an identifier to determine the party to send the unencrypted payload to. The keypairs are pre-generated and then copied into the docker volumes during the first time setup. For this implementation, Tessera configuration takes in a path where the keys are stored, and the same configuration is passed to the binary
  3. All Tessera keypairs are dynamically generated, so we need to store this in the stack state / persist them down to disk so that applications built on top have a reference point
  4. On top of the Tessera keypairs, private payloads are being stored in the Tessera database which is a configuration property. For the dev implementation, we chose to go with a h2 database that is automatically created within the docker volume if it does not exists. There are other ways of storing this data, such as using a Postgresql database, but for the purpose of a development environment, we feel that h2 is sufficient
  5. Tessera instances need to constantly poll each other on the p2p port to determine the status of the members that are connected to each other. The list of members and their endpoints are passed in as a configuration file when we call the Tessera binary. This configuration file is generated in the shell script of the docker entry-point file
  6. There are three API servers exposed for Tessera, q2t (9101), p2p (9000) and tp (9080). All three servers are on different ports and need to be exposed internally. Third party port is deliberately exposed on the host, since clients outside of the docker network can choose to use an external signer to hit the /storeraw endpoint, or require to perform health checks on the /upcheck endpoint
  7. Based on the number of members passed in to the CLI, that will determine the number of Quorum and Tessera containers that will be added to the docker compose. Each Quorum has it's own docker volume to store it's signer keys. Instead of having all keys for all members in a single Geth containers, each Quorum only has it's own signer keys. The same is being implemented for Tessera. Similar to the default implementation, we unlock the keys within the Quorum node itself
  8. EvmConnect needs to point to the correct Quorum node as per previous bullet point, instead of pointing to a single Geth node in the default implementation
  9. Discovery mechanism needs to be taken care of since there are multiple Blockchain nodes, this can be done either via bootnodes or a static list of quorum connection identifiers. We have implemented all Quorum nodes to use the first member's node as a bootstrap node to discover each other

Resolves https://github.com/hyperledger/firefly-cli/issues/309

rodion-lim-partior commented 1 week ago

@peterbroadhurst, I addressed your review comments and refactored the code. Also left a high level overview in the description of this PR, hope this helps to give a clearer picture on the changes that are being proposed. Thank you for taking the time to look through the large PR and the feedback provided.

EnriqueL8 commented 1 week ago

A few lint errors to fix as well:

Error: internal/blockchain/ethereum/quorum/private_transaction_manager.go:157:31: Error return value is not checked (errcheck)
    CopyTesseraEntrypointToVolume(ctx, outputDirectory, volumeName)
                                 ^
Error: internal/blockchain/ethereum/quorum/quorum.go:103:30: Error return value is not checked (errcheck)
    CopyQuorumEntrypointToVolume(ctx, outputDirectory, volumeName)
                                ^
Error: internal/blockchain/ethereum/quorum/private_transaction_manager.go:76:43: unslice: could simplify pubKeyBytes[:] to pubKeyBytes (gocritic)
    return privateKeyData.Data.Bytes, string(pubKeyBytes[:]), path, nil
                                             ^
Error: internal/blockchain/ethereum/quorum/quorum.go:28:121: ST1003: func parameter chainId should be chainID (stylecheck)
func CreateQuorumEntrypoint(ctx context.Context, outputDirectory, volumeName, memberIndex, consensus, stackName string, chainId int, tesseraEnabled bool) error {
                                                                                                                        ^
make: *** [Makefile:32: lint] Error 1
rodion-lim-partior commented 4 days ago

@EnriqueL8, addressed your comments and refactored most of the code accordingly. Will add additional tests for my bits in the next commit. Also raised two more issues on the remaining bits of the PR.

EnriqueL8 commented 4 days ago

Thanks, will give it another pass

rodion-lim-partior commented 3 days ago

@EnriqueL8, added more tests to increase the coverage. Had to do some refactoring on the non quorum packages to allow for that.