Important
This feature is only available in Canton Enterprise
Ethereum Domain¶
The Canton Enterprise Ethereum integration runs on an external Ethereum network. It is currently tested with Hyperledger Besu.
The Demo Deployment¶
To run the demo Canton Ethereum deployment, you will need access to a Canton Enterprise release, the Canton Enterprise docker repository , as well as having docker, docker-compose, and Hyperledger Besu (instructions here) installed.
Run the Demo Deployment¶
The demo Ethereum deployment can be found inside the examples
directory of the Canton Enterprise release. Unpack the Canton Enterprise release
and then cd
into examples/e03-ethereum-sequencer
.
The script ./ethereum-docker-compose/run.sh
from the folder examples
will create a new Besu testnet for the demo deployment and then start the demo.
In particular, the script will start several dockerised services:
- An ethereum testnet, using 4 Besu nodes with the IBFT consensus protocol.
- An instance of Canton. This includes two Participants and a Canton Enterprise
Domain with two Ethereum sequencers. The configuration for the canton instance
is in
ethereum-docker-compose/conf/config-example.conf
.
The environment variable CANTON_VERSION
is used to select the version of
Canton to use for the demo deployment. This should normally be set to the
version of the Canton Enterprise release being used, but can alternatively be
set to a different version or dev
for the latest main build of Canton.
Start the demo deployment as follows:
<<canton-release>>/examples/e03-ethereum-sequencer$ CANTON_VERSION=<your version> ./ethereum-docker-compose/run.sh
A new Besu testnet will be created and the demo will begin running with the created testnet. Once the demo is initialized and running, it will print out
******************************
Successfully initialized Canton-on-Ethereum
******************************
You will then be able to interact with the two participants via their ledger
APIs (or their admin APIs) respectively running on ports 5011
and 5021
(or 5012
and 5022
).
For example, you can start an instance of the Canton console to connect to the
two remote participants. You can find the Canton binary in bin/canton
of
the Canton Enterprise release artifact.
<<canton-release>>/examples/e03-ethereum-sequencer$ ../../bin/canton -c ethereum-docker-compose/conf/remote.conf
You can then perform various commands in the Canton console:
@ remoteParticipant1.id
res5: ParticipantId = ParticipantId(
UniqueIdentifier(Identifier("participant1"), Namespace(Fingerprint("01e69a39e2c821fc98eaeb22994b47084162122a01ebcb16dfb2514ccafcedd43d")))
)
@ remoteParticipant2.id
res6: ParticipantId = ParticipantId(
UniqueIdentifier(Identifier("participant2"), Namespace(Fingerprint("014aeb29dddff83678bc6f1194c363c6f0d18d3a6c9655927a7fb5adc84ec0532c")))
)
@ remoteParticipant1.domains.list_connected
res7: Seq[(com.digitalasset.canton.DomainAlias, com.digitalasset.canton.DomainId)] = List(
(Domain 'mydomain', mydomain::01537eb8...)
)
@ remoteParticipant1.health.ping(remoteParticipant2)
res8: concurrent.duration.Duration = 968 milliseconds
To shutdown and remove all Docker containers, you can execute stop-with-purge.sh
:
<<canton-release>>/examples/e03-ethereum-sequencer$ ./stop-with-purge.sh
Generating a Clean Testnet¶
The directory examples/e03-ethereum-sequencer/ibft-testnet
contains the
script generate-testnet.sh
. This automatically generates a clean Besu
network, including creating new randomised private keys. This is automatically
called by run.sh
but you may want to understand and edit this script to
create your own custom Besu deployment.
When generate-testnet.sh
is run:
- A genesis file and a set of keys for four Besu nodes are automatically
generated. These can be found in the folder
generated
. - The four Besu nodes are started.
- The state from any previous runs of
generate-testnet.sh
is deleted.
The generated testnet includes an instance of Canton’s Ethereum Sequencer
contract pre-deployed from genesis. This contract has the address
0x0ffd23af8eebc60b3cfdeed6f814988757237314
and is defined by the binary file
sequencer-binary
. The original Solidity source code of the Sequencer smart contract
is in <<canton-release>>/drivers/ethereum/solidity/Sequencer.sol
.
The generated Besu testnet has been configured largely following these tutorials:
- https://besu.hyperledger.org/en/stable/Tutorials/Private-Network/Create-IBFT-Network/
- and https://besu.hyperledger.org/en/stable/HowTo/Configure/FreeGas/
The parameters of the generated testnet can be changed by modifying the
genesis.json
file defined inline in generate-testnet.sh
.
Customization of the Demo Configuration¶
You can also modify the Canton configuration and bootstrap script for the demo.
The Canton configuration is found in
ethereum-docker-compose/conf/config-demo.conf
and the bootstrap script is
ethereum-docker-compose/ping.canton
. Note that if you change port mappings
in the Canton config file then you may also need to update
ethereum-docker-compose/docker-compose.yaml
.
The scaladoc documentation contains more details on the impact of specific Ethereum configuration options.
TLS configuration¶
Canton supports establishing a TLS connection to Ethereum client nodes. The demo showcases how to configure Canton to use mutual TLS authentication between Canton and one of the Besu nodes.
In particular, the bash script start-node.sh
, the mix-in Canton configuration tls.conf
and the certificates in ibft-testnet/tls
contain all settings pertaining to TLS.
If Canton is not configured to use TLS with an Ethereum node, it will attempt to communicate via a HTTP endpoint on the Ethereum node (and HTTPS for TLS).
For more details on the Canton configuration, please see the scaladocs of the TLS configuration.
For more details on how to configure Besu to accept TLS connections (as done in the demo, see especially file start-node.sh
), please see the Besu documentation.
Configuring a wallet file¶
Canton allows configuring a wallet in UTC JSON and BIP 39 format.
The Ethereum demo includes an example of a mix-in wallet configuration for a BIP39-based wallet in ethereum-docker-compose/conf/wallet.conf
.
A UTC JSON wallet configuration could look as follows:
canton.sequencers.ethereumSequencer1.sequencer.config.wallet {
type = "utc-json-wallet"
password = "supersafe"
wallet-path = "./enterprise/app/src/test/resources/ethereum/wallet.json"
}
For more details, please refer to the Canton scaladoc documentation.
Deployment to an existing Ethereum Network¶
The demo deploys the Ethereum sequencer contract by passing it to the bootstrap node and deploying it in the genesis block. This isn’t possible when attempting to use the Ethereum sequencer with an existing and already running network or blockchain. To deploy the Ethereum sequencer with an existing Ethereum network, we expose the utility console command deploy_sequencer_contract. Deployment to an existing network then works as follows:
1. Configure the Ethereum sequencer to be able to connect to the network but set the contract address and deployment height within the SequencerContractConfig to dummy values as these will be ignored for now.
If you want to try these steps with the demo, you don’t need to change anything in the configuration.
2. Create a bootstrap script that deploys the sequencer contract to the configured network via calling deploy_sequencer_contract
. For example, for the demo we use script sequencer_deployment.canton with the following content:
val (address, block) = ethereumSequencer1.ethereum.deploy_sequencer_contract
println(s"Sequencer contract successfully deployed to contract address `$address` in block `$block`")
It is important to specify --manual-start
so the Canton nodes aren’t started automatically when running the bootstrap script and Canton does not try to load the configured sequencer contract it expects at the
address specified within the SequencerContractConfig
.
- Start Canton and execute the bootstrap script. For the demo, you will need to change client-host for ethereumSequencer1 and ethereumSequencer2 from respectively besu-1 and besu-2 to 127.0.0.1 in conf/config-example.conf. Then run the following command:
<<canton-release>>/bin/canton run ethereum-docker-compose/sequencer_deployment.canton --config ethereum-docker-compose/conf/config-example.conf --manual-start
You should see output similar to the following:
Sequencer contract successfully deployed to contract address `0x68f21d0613f2c9b1e677f09ba6a9eb0980d6d5c1` in block `506`
Stop Canton next (exit
).
- Update the contract address and deployment height in the
SequencerContractConfig
configuration (fileethereum-docker-compose/conf/config-example.conf
for the demo) with the output from the previous step. - Start Canton normally, e.g., with the following command for the demo:
<<canton-release>>/bin/canton --config ethereum-docker-compose/conf/config-example.conf --bootstrap ethereum-docker-compose/ping.canton
If everything went well, you should see the ping succeeding and the interactive console starting.
Requirements for the Ethereum Network¶
The Canton Ethereum integration is currently tested with a Hyperledger Besu free gas network, running with the IBFT 2.0 consensus protocol. However, the integration only interfaces with the Ethereum client via web3j so most popular Ethereum clients (eg Geth and Parity) should be supported. There are, however, some requirements for the Ethereum Network irrespective of the Ethereum client you choose to use:
- Currently, a free gas network is required. This means setting the gas price to zero.
- The block size limit (often measured in gas, and sometimes referred to as the ‘gas limit’) must be larger than any message to be sequenced. It is recommended to set this parameter as high as possible.
- The contract size limit must be big enough for the Canton Ethereum Domain to store all required state for sequencing messages. It is recommended to set this parameter as high as possible.
- Proof of authority protocols are recommended over proof of work.
- Currently, consensus protocols must have immediate finality. This means that ledger forks should not occur with the chosen consensus protocol.
Furthermore, we also have some suggestions to improve throughput and latency irrespective of the choice of Ethereum client.
Throughput¶
Generally, the throughput of a Canton system using Ethereum-based sequencers is limited by the throughput of the Ethereum client. Thus, if an Ethereum-based sequencer does not deliver the desired throughput, the throughput and deployment of the Ethereum clients should be optimized in the first instance. For Besu performance optimization, some recommendations can be found in the Besu documentation - in particular, it is crucial to use a fast storage media.
Latency¶
Within a Canton transaction, there are three sequential sequencing steps, that is, a single Canton transaction leads to at least three sequential messages sent to the sequencer.
This is illustrated, e.g., in the message sequence diagram of the Canton 101 section.
As a result, a Canton transaction also leads to at least three Ethereum transactions within three different blocks.
Thus, to achieve relatively low latencies, the Ethereum network networks must be configured with a frequent block mining frequency (configured via blockperiodseconds
in Besu)
and ideally co-located with the Canton sequencer node. A block mining frequency of at
least one block per second is recommended.
Trust Properties of the Ethereum Sequencer Integration¶
The demo integration uses two participants and two different Ethereum Sequencer nodes. Each participant chooses its preferred Ethereum Sequencer node, and this node performs reads and writes on behalf of the participant. Therefore, each participant must trust its chosen Ethereum Sequencer node. Additionally, each participant must trust some proportion of the nodes in the Ethereum network as determined by the consensus protocol.