# testnet-onboarding-demo ## Setup ### Laconic Wallet - Install laconic wallet using [latest APK release](https://git.vdb.to/cerc-io/laconic-wallet/releases) - Download the APK file in latest release `laconic-wallet-debug.apk` - Install the APK on your device - It will need third party installation permission to install the APK - (Optional) Build laconic wallet from source by following the steps below - Follow the [Install](https://git.vdb.to/cerc-io/laconic-wallet#install) steps from the laconic-wallet README to setup Android Studio - Clone the repository ```bash git clone git@git.vdb.to:cerc-io/laconic-wallet.git ``` - Enter the project directory ```bash cd laconic-wallet ``` - Setup .env - Copy and update [`.env`](./.env) ```bash cp .env.example .env ``` - In the `.env` file add your WalletConnect project id. You can generate your own ProjectId at (use `gmail` address) ```bash WALLET_CONNECT_PROJECT_ID=39bc93c... ``` - Install dependencies ```bash yarn ``` - Exit project repo ```bash cd ../ ``` ### Testnet Onboarding App - Clone the repository ```bash git clone git@git.vdb.to:cerc-io/testnet-onboarding-app.git ``` - Enter the project directory ```bash cd testnet-onboarding-app ``` - Setup .env - Copy and update `.env` ```bash cp .env.example .env ``` - In the `.env` file, add the WalletConnect project ID used in your [laconic-wallet](https://git.vdb.to/cerc-io/laconic-wallet) setup. ```bash WALLET_CONNECT_PROJECT_ID=39bc93c... ``` - Install dependencies ```bash yarn ``` - Exit project repo ```bash cd ../ ``` ### Stack Orchestrator - Follow these steps to install laconic-so: ### fixturenet-laconicd and laconic-faucet Stacks - Clone the stack repos: ```bash laconic-so fetch-stack git.vdb.to/cerc-io/fixturenet-laconicd-stack --git-ssh --pull laconic-so fetch-stack git.vdb.to/cerc-io/testnet-laconicd-stack --git-ssh --pull ``` - Clone required repositories: ```bash # laconicd laconic-so --stack ~/cerc/fixturenet-laconicd-stack/stack-orchestrator/stacks/fixturenet-laconicd setup-repositories --git-ssh --pull laconic-so --stack ~/cerc/testnet-laconicd-stack/stack-orchestrator/stacks/laconic-faucet setup-repositories --git-ssh --pull ``` - Build the container images: ```bash # laconicd laconic-so --stack ~/cerc/fixturenet-laconicd-stack/stack-orchestrator/stacks/fixturenet-laconicd build-containers --force-rebuild laconic-so --stack ~/cerc/testnet-laconicd-stack/stack-orchestrator/stacks/laconic-faucet build-containers --force-rebuild ``` - Create a deployment for stage 0: - Create spec files for the deployment: ```bash laconic-so --stack ~/cerc/fixturenet-laconicd-stack/stack-orchestrator/stacks/fixturenet-laconicd deploy init --output stage0-spec.yml ``` - Edit `network` in the spec file to map container ports to host ports as required: ```bash # stage0-spec.yml ... network: ports: laconicd: - '6060' - '26657:26657' - '26656:26656' - '9473:9473' - '9090:9090' - '1317:1317' ``` - Create a deployment from the spec file: ```bash laconic-so --stack ~/cerc/fixturenet-laconicd-stack/stack-orchestrator/stacks/fixturenet-laconicd deploy create --spec-file stage0-spec.yml --deployment-dir stage0-deployment ``` - In `stage0-deployment/config.env` file, set the following env variable: ```bash # Set to true to enable adding participants functionality of the onboarding module ONBOARDING_ENABLED=true ``` - Create a deployment for stage 1: - Create spec file for the deployment: ```bash laconic-so --stack ~/cerc/fixturenet-laconicd-stack/stack-orchestrator/stacks/fixturenet-laconicd deploy init --output stage1-spec.yml ``` - Copy the contents of `stage0-spec.yml` to `stage1-spec.yml`: ```bash cp stage0-spec.yml stage1-spec.yml ``` - Create a deployment from the spec file: ```bash laconic-so --stack ~/cerc/fixturenet-laconicd-stack/stack-orchestrator/stacks/fixturenet-laconicd deploy create --spec-file stage1-spec.yml --deployment-dir stage1-deployment ``` - Create a deployment for laconic-faucet: - Create spec file for the deployment: ```bash laconic-so --stack ~/cerc/testnet-laconicd-stack/stack-orchestrator/stacks/laconic-faucet deploy init --output laconic-faucet-spec.yml ``` - Edit `network` in the spec file to map container port to host port as required: ```bash # laconic-faucet-spec.yml ... network: ports: laconic-faucet: - '4000:3000' ``` - Create a deployment from the spec file: ```bash laconic-so --stack ~/cerc/testnet-laconicd-stack/stack-orchestrator/stacks/laconic-faucet deploy create --spec-file laconic-faucet-spec.yml --deployment-dir laconic-faucet-deployment # Place in the same namespace as stage0 cp stage0-deployment/deployment.yml laconic-faucet-deployment/deployment.yml ``` ### L1 eth and L2 Optimism Stacks - Clone the stack repo: ```bash laconic-so fetch-stack git.vdb.to/cerc-io/fixturenet-eth-stacks --pull laconic-so fetch-stack git.vdb.to/cerc-io/fixturenet-optimism-stack --pull ``` - Clone required repositories: ```bash # L1 (fixturenet-eth) laconic-so --stack ~/cerc/fixturenet-eth-stacks/stack-orchestrator/stacks/fixturenet-eth setup-repositories --pull # L2 (optimism) laconic-so --stack ~/cerc/fixturenet-optimism-stack/stack/fixturenet-optimism setup-repositories --pull # If this throws an error as a result of being already checked out to a branch/tag in a repo, remove all repositories from that stack and re-run the command # The repositories are located in $HOME/cerc by default ``` - Build the container images: ```bash # Remove any older foundry image with `latest` tag docker rmi ghcr.io/foundry-rs/foundry:latest # L1 (fixturenet-eth) laconic-so --stack ~/cerc/fixturenet-eth-stacks/stack-orchestrator/stacks/fixturenet-eth build-containers --force-rebuild # L2 (optimism) laconic-so --stack ~/cerc/fixturenet-optimism-stack/stack/fixturenet-optimism build-containers --force-rebuild # If errors are thrown during build, old images used by this stack would have to be deleted ``` - NOTE: this will take >10 mins depending on the specs of your machine, and **requires** 16GB of memory or greater. - Remove any dangling Docker images (to clear up space): ```bash docker image prune ``` - Create spec files for deployments, which will map the stack's ports and volumes to the host: ```bash laconic-so --stack ~/cerc/fixturenet-eth-stacks/stack-orchestrator/stacks/fixturenet-eth deploy init --output fixturenet-eth-spec.yml laconic-so --stack ~/cerc/fixturenet-optimism-stack/stack/fixturenet-optimism deploy init --output fixturenet-optimism-spec.yml ``` - Configure ports: - `fixturenet-eth-spec.yml` ```yml ... network: ports: fixturenet-eth-bootnode-geth: - '9898:9898' - '30303' fixturenet-eth-geth-1: - '8545:8545' - '8546:8546' - '40000' - '6060' fixturenet-eth-lighthouse-1: - '8001' ... ``` - `fixturenet-optimism-spec.yml` ```yml ... network: ports: op-geth: - '9545:8545' - '9546:8546' ... ``` - Create deployments: Once you've made any needed changes to the spec files, create deployments from them: ```bash laconic-so --stack ~/cerc/fixturenet-eth-stacks/stack-orchestrator/stacks/fixturenet-eth deploy create --spec-file fixturenet-eth-spec.yml --deployment-dir fixturenet-eth-deployment laconic-so --stack ~/cerc/fixturenet-optimism-stack/stack/fixturenet-optimism deploy create --spec-file fixturenet-optimism-spec.yml --deployment-dir fixturenet-optimism-deployment # Place them both in the same namespace (cluster) cp fixturenet-eth-deployment/deployment.yml fixturenet-optimism-deployment/deployment.yml ``` - Env configuration: ```bash cat < fixturenet-eth-deployment/config.env CERC_ALLOW_UNPROTECTED_TXS=true EOF ``` ### Go Nitro - Clone the stack repo: ```bash laconic-so fetch-stack git.vdb.to/cerc-io/nitro-stack --git-ssh --pull ``` - Clone required repositories: ```bash laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/nitro-node setup-repositories --git-ssh --pull ``` - Build the container images: ```bash laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/nitro-node build-containers --force-rebuild ``` - Create a deployment spec-file for Alice's L1 nitro-node: - Create spec files for the deployment: ```bash laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/nitro-node deploy init --output l1alice-nitro-spec.yml ``` - Edit `network` in the spec file to map container ports to host ports as required: ```bash # l1alice-nitro-spec.yml ... network: ports: nitro-node: - 3007:3005 - 4007:4005 ``` - Create a deployment spec-file for Charlie's L1 nitro-node: - Create spec file for the deployment: ```bash laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/nitro-node deploy init --output l1charlie-nitro-spec.yml ``` - Edit `network` in the spec file to map container ports to host ports as required: ```bash # l1charlie-nitro-spec.yml ... network: ports: nitro-node: - 3008:3005 - 4008:4005 ``` - Create a deployment spec-file for Alice's L2 nitro-node: - Create spec files for the deployment: ```bash laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/nitro-node deploy init --output l2alice-nitro-spec.yml ``` - Edit `network` in the spec file to map container ports to host ports as required: ```bash # l2alice-nitro-spec.yml ... network: ports: nitro-node: - 3009:3005 - 4009:4005 ``` - Create a deployment spec-file for Charlie's L2 nitro-node: - Create spec file for the deployment: ```bash laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/nitro-node deploy init --output l2charlie-nitro-spec.yml ``` - Edit `network` in the spec file to map container ports to host ports as required: ```bash # l2charlie-nitro-spec.yml ... network: ports: nitro-node: - 3010:3005 - 4010:4005 ``` ## Run - Start L1, L2 stacks: (run steps in directory where the stack deployments had been created) - Start `fixturenet-eth-deployment` deployment: ```bash laconic-so deployment --dir fixturenet-eth-deployment start ``` - Check status of L1 - Run command in intervals of 3 seconds to check if new blocks are created ```bash laconic-so deployment --dir fixturenet-eth-deployment exec foundry "cast block-number" ``` - Check geth logs to ensure that new blocks are getting created ```bash laconic-so deployment --dir fixturenet-eth-deployment logs -f fixturenet-eth-geth-1 ``` - Start `fixturenet-optimism-deployment` deployment: ```bash laconic-so deployment --dir fixturenet-optimism-deployment start ``` NOTE: The `fixturenet-optimism-contracts` service will configure and deploy the Optimism contracts to L1, exiting when complete. This may take several minutes; you can follow the progress by following the container's logs - Check L2 logs ```bash laconic-so deployment --dir fixturenet-optimism-deployment logs -f op-geth # Ensure new blocks are getting created ``` - Send ETH from L1 to L2 (run steps in directory where the stack deployments had been created) - Get information about funded accounts on L1 ```bash curl 127.0.0.1:9898/accounts.csv ``` - Send some ETH from the desired account to the `L1StandardBridgeProxy` contract on L1 to bridge it to L2: - Set the following variables: ```bash L1_RPC=http://fixturenet-eth-geth-1:8545 L2_RPC=http://op-geth:8545 DEPLOYMENT_CONTEXT=1212 ACCOUNT=0xe6CE22afe802CAf5fF7d3845cec8c736ecc8d61F ``` - Read the bridge contract address from the L1 deployment records in the `op-node` container: ```bash BRIDGE=$(laconic-so deployment --dir fixturenet-optimism-deployment exec op-node "cat /l1-deployment/$DEPLOYMENT_CONTEXT-deploy.json" | jq -r .L1StandardBridgeProxy) # Get the funded account's pk ACCOUNT_PK=$(laconic-so deployment --dir fixturenet-optimism-deployment exec op-node "jq -r '.AdminKey' /l2-accounts/accounts.json") ``` - Use cast to send ETH to the bridge contract: ```bash laconic-so deployment --dir fixturenet-eth-deployment exec foundry "cast send --from $ACCOUNT --value 1ether $BRIDGE --rpc-url $L1_RPC --private-key $ACCOUNT_PK" ``` NOTE: This is for sending funds to the contracts deployer account which is also the Bridge node account - Allow a couple minutes for the bridge to complete - Check balance on L2 ```bash laconic-so deployment --dir fixturenet-eth-deployment exec foundry "cast balance $ACCOUNT --rpc-url $L2_RPC" # 100000000000000000 ``` - Run the bridge: - Create a spec-file for the deployment, map container ports to host ports and set env variables: ```bash laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/bridge deploy init --map-ports-to-host any-same --output bridge-nitro-spec.yml --config "NITRO_L1_CHAIN_URL=ws://host.docker.internal:8546,NITRO_L2_CHAIN_URL=ws://host.docker.internal:9546,NITRO_CHAIN_PK=888814df89c4358d7ddb3fa4b0213e7331239a80e1f013eaa7b2deca2a41a218,NITRO_SC_PK=0279651921cd800ac560c21ceea27aab0107b67daf436cdd25ce84cad30159b4,GETH_URL=http://host.docker.internal:8545,OPTIMISM_URL=http://host.docker.internal:9545,GETH_DEPLOYER_PK=$ACCOUNT_PK,OPTIMISM_DEPLOYER_PK=$ACCOUNT_PK,TOKEN_NAME=LaconicNetworkToken,TOKEN_SYMBOL=LNT,INITIAL_TOKEN_SUPPLY=129600" ``` - Create a deployment from the spec file: ```bash laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/bridge deploy create --spec-file bridge-nitro-spec.yml --deployment-dir bridge-deployment ``` - Start the nitro bridge ```bash laconic-so deployment --dir bridge-deployment start # Check the logs, ensure that the node is running laconic-so deployment --dir bridge-deployment logs nitro-bridge -f ``` - Send custom tokens to Alice and Charlie on L1 - Export variables for L1 token address ```bash export L1_ASSET_ADDRESS="$(laconic-so deployment --dir bridge-deployment exec nitro-contracts "jq -r '.\"1212\"[0].contracts.Token.address' /app/deployment/nitro-addresses.json")" export A_CHAIN_ADDRESS="0xe22AD83A0dE117bA0d03d5E94Eb4E0d80a69C62a" export C_CHAIN_ADDRESS="0xf1ac8Dd1f6D6F5c0dA99097c57ebF50CD99Ce293" ``` - Send tokens to Alice and Charlie ```bash # Send tokens to Alice laconic-so deployment --dir bridge-deployment exec nitro-contracts "cd packages/nitro-protocol && yarn hardhat transfer --contract $L1_ASSET_ADDRESS --to $A_CHAIN_ADDRESS --amount 1000 --network geth" #Send tokens to Charlie laconic-so deployment --dir bridge-deployment exec nitro-contracts "cd packages/nitro-protocol && yarn hardhat transfer --contract $L1_ASSET_ADDRESS --to $C_CHAIN_ADDRESS --amount 1000 --network geth" ``` - Start testnet-onboarding-app (run command in testnet-onboarding-app repo) ```bash # In testnet-onboarding-app yarn start ``` NOTE: Ignore source map warnings in the terminal - Run Laconic Wallet - Connect your phone with the PC (Make sure that USB debugging is enabled on your phone) - Setup port forwarding for your device using the following command: ```bash # Get device id adb devices # Setup port forwarding adb -s reverse tcp:26657 tcp:26657 ``` - Open Laconic Wallet app that was installed from the APK - (Optional) Start `laconic-wallet` android app (run steps in laconic-wallet repo) - Set up the Android device - For a physical device, refer to the [React Native documentation for running on a physical device](https://reactnative.dev/docs/running-on-device) - For a virtual device, continue with the steps - Start the application: ```bash # In laconic-wallet yarn start ``` - Press `a` to run the application on android and wait till the wallet app opens up on your phone - In laconic-wallet app, click on `Create wallet` and add laconicd chain using `Add network` button: ```bash Network type - `COSMOS` chain ID - `laconic_9000-1` Network name - `laconicd` New RPC URL - `http://127.0.0.1:26657` Coin Type - `118` Native Denom - `photon` Address Prefix - `laconic` Gas Price - `0.01` ``` ## Demo - Start the stack for stage 0 laconicd (run command in directory where stage0-deployment had been created) ```bash laconic-so deployment --dir stage0-deployment start # Check the logs, ensure that new blocks are getting created laconic-so deployment --dir stage0-deployment logs laconicd -f ``` - Run laconic-faucet: - Get private key of funded faucet account from stage 0 laconicd chain: ```bash export FAUCET_ACCOUNT_PK=$(laconic-so deployment --dir stage0-deployment exec laconicd "echo y | laconicd keys export alice --keyring-backend test --unarmored-hex --unsafe") ``` - Set the env config for faucet deployment: ```bash cat < laconic-faucet-deployment/config.env CERC_FAUCET_KEY=$FAUCET_ACCOUNT_PK EOF ``` - Start the stack for laconic-faucet: ```bash laconic-so deployment --dir laconic-faucet-deployment start ``` - Get the deployed nitro contract addresses (run in the directory where the deployments were created): ```bash # Nitro contract addresses export NA_ADDRESS=$(laconic-so deployment --dir bridge-deployment exec nitro-bridge "jq -r '.\"1212\"[0].contracts.NitroAdjudicator.address' /app/deployment/nitro-addresses.json") export CA_ADDRESS=$(laconic-so deployment --dir bridge-deployment exec nitro-bridge "jq -r '.\"1212\"[0].contracts.ConsensusApp.address' /app/deployment/nitro-addresses.json") export VPA_ADDRESS=$(laconic-so deployment --dir bridge-deployment exec nitro-bridge "jq -r '.\"1212\"[0].contracts.VirtualPaymentApp.address' /app/deployment/nitro-addresses.json") # Contract address of bridge export BRIDGE_ADDRESS=$(laconic-so deployment --dir bridge-deployment exec nitro-bridge "jq -r '.\"42069\"[0].contracts.Bridge.address' /app/deployment/nitro-addresses.json") ``` - In the wallet, add 2 accounts (Alice and Charlie) for both the networks (ethereum and laconicd) by selecting the network and clicking on `Add account` - Get Ethereum private keys for accounts Alice and Charlie from wallet using the `Show private key` link (to be used as statechannel PKs) ```bash export A_PRIVATE_KEY= export C_PRIVATE_KEY= ``` - Prepare deployments for the nodes - Create a deployment `l1alice-nitro-deployment` from the spec file ```bash laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/nitro-node deploy create --spec-file l1alice-nitro-spec.yml --deployment-dir l1alice-nitro-deployment ``` - Set the env variables for L1 Alice's nitro-node: ```bash cat < l1alice-nitro-deployment/config.env NITRO_CHAIN_URL=ws://host.docker.internal:8546 NITRO_SC_PK=$A_PRIVATE_KEY NITRO_CHAIN_PK=570b909da9669b2f35a0b1ac70b8358516d55ae1b5b3710e95e9a94395090597 NA_ADDRESS=$NA_ADDRESS VPA_ADDRESS=$VPA_ADDRESS CA_ADDRESS=$CA_ADDRESS BRIDGE_ADDRESS=$BRIDGE_ADDRESS NITRO_BOOTPEERS=/dns4/host.docker.internal/tcp/3005/p2p/16Uiu2HAmJDxLM8rSybX78FH51iZq9PdrwCoCyyHRBCndNzcAYMes NITRO_EXT_MULTIADDR=/dns4/host.docker.internal/tcp/3007 EOF ``` - Create a deployment `l1charlie-nitro-deployment` from the spec file ```bash laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/nitro-node deploy create --spec-file l1charlie-nitro-spec.yml --deployment-dir l1charlie-nitro-deployment ``` - Set the env variables for L1 Charlie's nitro-node: ```bash cat < l1charlie-nitro-deployment/config.env NITRO_CHAIN_URL=ws://host.docker.internal:8546 NITRO_SC_PK=$C_PRIVATE_KEY NITRO_CHAIN_PK=111b7500bdce494d6f4bcfe8c2a0dde2ef92f751d9070fac6475dbd6d8021b3f NA_ADDRESS=$NA_ADDRESS VPA_ADDRESS=$VPA_ADDRESS CA_ADDRESS=$CA_ADDRESS BRIDGE_ADDRESS=$BRIDGE_ADDRESS NITRO_BOOTPEERS=/dns4/host.docker.internal/tcp/3005/p2p/16Uiu2HAmJDxLM8rSybX78FH51iZq9PdrwCoCyyHRBCndNzcAYMes NITRO_EXT_MULTIADDR=/dns4/host.docker.internal/tcp/3008 EOF ``` - Create a deployment `l2alice-nitro-deployment` from the spec file: ```bash laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/nitro-node deploy create --spec-file l2alice-nitro-spec.yml --deployment-dir l2alice-nitro-deployment ``` - Set the env variables for L2 Alice's nitro-node: ```bash cat < l2alice-nitro-deployment/config.env NITRO_CHAIN_URL=ws://host.docker.internal:9546 NITRO_SC_PK=$A_PRIVATE_KEY NITRO_CHAIN_PK=570b909da9669b2f35a0b1ac70b8358516d55ae1b5b3710e95e9a94395090597 NA_ADDRESS=$NA_ADDRESS VPA_ADDRESS=$VPA_ADDRESS CA_ADDRESS=$CA_ADDRESS BRIDGE_ADDRESS=$BRIDGE_ADDRESS NITRO_BOOTPEERS=/dns4/host.docker.internal/tcp/3006/p2p/16Uiu2HAmJDxLM8rSybX78FH51iZq9PdrwCoCyyHRBCndNzcAYMes NITRO_EXT_MULTIADDR=/dns4/host.docker.internal/tcp/3009 NITRO_L2=true EOF ``` - Create deployment `l2charlie-nitro-deployment` from the spec files: ```bash laconic-so --stack ~/cerc/nitro-stack/stack-orchestrator/stacks/nitro-node deploy create --spec-file l2charlie-nitro-spec.yml --deployment-dir l2charlie-nitro-deployment ``` - Set the env variables for L2 Charlie's nitro-node: ```bash cat < l2charlie-nitro-deployment/config.env NITRO_CHAIN_URL=ws://host.docker.internal:9546 NITRO_SC_PK=$C_PRIVATE_KEY NITRO_CHAIN_PK=111b7500bdce494d6f4bcfe8c2a0dde2ef92f751d9070fac6475dbd6d8021b3f NA_ADDRESS=$NA_ADDRESS VPA_ADDRESS=$VPA_ADDRESS CA_ADDRESS=$CA_ADDRESS BRIDGE_ADDRESS=$BRIDGE_ADDRESS NITRO_BOOTPEERS=/dns4/host.docker.internal/tcp/3006/p2p/16Uiu2HAmJDxLM8rSybX78FH51iZq9PdrwCoCyyHRBCndNzcAYMes NITRO_EXT_MULTIADDR=/dns4/host.docker.internal/tcp/3010 NITRO_L2=true EOF ``` - Start nitro nodes for Alice and Charlie on L1 and L2: - Start the deployment for Alice's L1 node ```bash laconic-so deployment --dir l1alice-nitro-deployment start # Check the logs, ensure that the node is running laconic-so deployment --dir l1alice-nitro-deployment logs nitro-node -f ``` - Start the deployment for Charlie's L1 node ```bash laconic-so deployment --dir l1charlie-nitro-deployment start # Check the logs, ensure that the node is running laconic-so deployment --dir l1charlie-nitro-deployment logs nitro-node -f ``` - Start the deployment for Alice's L2 node ```bash laconic-so deployment --dir l2alice-nitro-deployment start # Check the logs, ensure that the node is running laconic-so deployment --dir l2alice-nitro-deployment logs nitro-node -f ``` - Start the deployment for Charlie's L2 node ```bash laconic-so deployment --dir l2charlie-nitro-deployment start # Check the logs, ensure that the node is running laconic-so deployment --dir l2charlie-nitro-deployment logs nitro-node -f ``` - Create ledger channels on L1 and mirrored channels on L2 - Open new terminal, check that no channels exist on L2 ```bash laconic-so deployment --dir bridge-deployment exec nitro-rpc-client "nitro-rpc-client get-all-l2-channels -p 4006 -h nitro-bridge" ``` - Set address of bridge and address of custom token on L1 in the current terminal ```bash export BRIDGE_NITRO_ADDRESS=0xBBB676f9cFF8D242e9eaC39D063848807d3D1D94 export L1_ASSET_ADDRESS="$(laconic-so deployment --dir bridge-deployment exec nitro-contracts "jq -r '.\"1212\"[0].contracts.Token.address' /app/deployment/nitro-addresses.json")" ``` - Create ledger channel between A and Bridge with custom token ```bash laconic-so deployment --dir l1alice-nitro-deployment exec nitro-rpc-client "nitro-rpc-client direct-fund $BRIDGE_NITRO_ADDRESS --assetAddress $L1_ASSET_ADDRESS -p 4005 -h nitro-node" ``` - Once direct-fund objective is complete, bridge will create mirrored channel on L2 - Check node A' logs to see bridged-fund objective completed - Check the [Troubleshooting](#troubleshooting) section if command to create a ledger channel fails or gets stuck - Check status of L1 ledger channel between A and Bridge ```bash laconic-so deployment --dir l1alice-nitro-deployment exec nitro-rpc-client "nitro-rpc-client get-ledger-channel -p 4005 -h nitro-node" # Expected output: # { # ID: '0x161d289a50222caa781db215bb82a3ede4f557217742245525b8e8cbff04ec21', # Status: 'Open', # Balance: { # AssetAddress: '', # Me: '0xaaa6628ec44a8a742987ef3a114ddfe2d4f7adce', # Them: '0xbbb676f9cff8d242e9eac39d063848807d3d1d94', # MyBalance: 1000000n, # TheirBalance: 1000000n # }, # ChannelMode: 'Open' # } ``` - Create ledger channel between C and Bridge with custom token ```bash laconic-so deployment --dir l1charlie-nitro-deployment exec nitro-rpc-client "nitro-rpc-client direct-fund $BRIDGE_NITRO_ADDRESS --assetAddress $L1_ASSET_ADDRESS -p 4005 -h nitro-node" ``` - Once direct fund objective is complete, bridge will create mirrored channel on L2 - Check node C' logs to see bridged-fund objective completed - Check the [Troubleshooting](#troubleshooting) section if command to create a ledger channel fails or gets stuck - Check status of L1 ledger channel between C and Bridge ```bash laconic-so deployment --dir l1charlie-nitro-deployment exec nitro-rpc-client "nitro-rpc-client get-ledger-channel -p 4005 -h nitro-node" # Expected output: # { # ID: '0x69a3f09b6f4f94f033cf084e6e4a9453438c45b43606e9a95f5434f4c6527543', # Status: 'Open', # Balance: { # AssetAddress: '', # Me: '0xa8d2d06ace9c7ffc24ee785c2695678aecdfd7a0', # Them: '0xbbb676f9cff8d242e9eac39d063848807d3d1d94', # MyBalance: 1000000n, # TheirBalance: 1000000n # }, # ChannelMode: 'Open' # } ``` - Check status of all L2 mirrored ledger channels ```bash laconic-so deployment --dir bridge-deployment exec nitro-rpc-client "nitro-rpc-client get-all-l2-channels -p 4006 -h nitro-bridge" # Expected output: # {"ID":"0x15dbe6b996e4e46fdd6ea3e2074cbca58014dbb07368e3e7ba286df5c7b9da0d","Status":"Open","Balance":{"AssetAddress":"","Me":"0xbbb676f9cff8d242e9eac39d063848807d3d1d94","Them":"0xa8d2d06ace9c7ffc24ee785c2695678aecdfd7a0","MyBalance":1000000,"TheirBalance":1000000},"ChannelMode":"Open"} # {"ID":"0x6a9f5ccf1fa802525d794f4a899897f947615f6acc7141e61e056a8bfca29179","Status":"Open","Balance":{"AssetAddress":"","Me":"0xbbb676f9cff8d242e9eac39d063848807d3d1d94","Them":"0xaaa6628ec44a8a742987ef3a114ddfe2d4f7adce","MyBalance":1000000,"TheirBalance":1000000},"ChannelMode":"Open"} ``` In above expected output the following are observed - In ledger channel with ID `0x15dbe6b996e4e46fdd6ea3e2074cbca58014dbb07368e3e7ba286df5c7b9da0d` - Alice is a participant since `Them` address is `0xa8d2d06ace9c7ffc24ee785c2695678aecdfd7a0` - Alice amount is `1000000` since `TheirBalance` corresponds to her amount - In ledger channel with ID `0x6a9f5ccf1fa802525d794f4a899897f947615f6acc7141e61e056a8bfca29179` - Charlie is participant since `Them` address is `0xaaa6628ec44a8a742987ef3a114ddfe2d4f7adce` - Charlie amount is `1000000` since `TheirBalance` corresponds to his amount - Onboard participants - Open the `testnet-onboarding-app` at - Connect to the testnet-onboarding app by clicking on the WalletConnect icon on the top right corner in the wallet and scanning QR code of the app - Choose Alice's nitro and laconicd account to onboard - Use nitro accounts for which ledger channels have been created on L2 - Sign using the nitro key - Approve sign request on Wallet - Fund the laconic account by clicking on the `REQUEST TOKENS FROM FAUCET` button - Send transaction request to the Wallet - Approve and send transaction to laconicd chain - Repeat onboarding for other (Charlies's) account by clicking on the web app header "Testnet Onboarding" - List the participants on stage 1 (run in the directory where laconicd deployment was created): ```bash laconic-so deployment --dir stage0-deployment exec laconicd "laconicd query onboarding list" # Expected output # - cosmos_address: # ethereum_address: # - cosmos_address: # ethereum_address: ``` - Halt the stage 0 laconicd deployment: ```bash # Run where deployments are created laconic-so deployment --dir stage0-deployment stop ``` - Use the scripts in fixturenet-laconicd stack to generate genesis file for stage 1 with token allocations: ```bash cd ~/cerc/fixturenet-laconicd-stack/stack-orchestrator/stacks/fixturenet-laconicd ./scripts/generate-stage1-genesis.sh # Expected output: # Genesis file for stage1 written to output/genesis.json # Remove the temporary data directory sudo rm -rf stage1-genesis # Go back to the directory where deployments are created cd - ``` - Copy over the generated genesis file (`.json`) containing the onboarding module state with funded participants to data directory in stage1 deployment (`stage1-deployment/data/genesis-config`): ```bash # Run where deployments are created cp ~/cerc/fixturenet-laconicd-stack/stack-orchestrator/stacks/fixturenet-laconicd/output/genesis.json stage1-deployment/data/genesis-config/genesis.json ``` - Start the deployment for stage 1 ```bash laconic-so deployment --dir stage1-deployment start ``` - The `bank` module transfers are disabled on stage 1 laconicd - Query the list of registered participants in stage 1 laconicd: ```bash laconic-so deployment --dir stage1-deployment exec laconicd "laconicd query onboarding list" # Expected output: same as the result from stage0-deployment ``` - Query the balances of registered participants: ```bash export A_LACONIC_ADDRESS= export C_LACONIC_ADDRESS= laconic-so deployment --dir stage1-deployment exec laconicd "laconicd query bank balances $A_LACONIC_ADDRESS" laconic-so deployment --dir stage1-deployment exec laconicd "laconicd query bank balances $C_LACONIC_ADDRESS" # Expected output: Account balances equal to Alice's and Charlie's holdings on the bridge ``` - The bridge holdings are therefore reflected on stage 1 laconicd chain as genesis allocations - TODO: The registered participants with balances on stage 1 laconicd chain can join as validators - ### Payments Demo in L2 - Create virtual channel on L2 from A' to C' via Bridge' as intermediary - Get Nitro (Ethereum) addresses for Alice and Charlie from the wallet: ```bash export A_ADDRESS= export C_ADDRESS= # Bridge's Nitro address export BRIDGE_NITRO_ADDRESS=0xBBB676f9cFF8D242e9eaC39D063848807d3D1D94 ``` - Create a virtual channel: ```bash # Starts virtual fund objective on L2 to create virtual channel from A' to C' laconic-so deployment --dir l2alice-nitro-deployment exec nitro-rpc-client "nitro-rpc-client virtual-fund $C_ADDRESS $BRIDGE_NITRO_ADDRESS --amount 1000 -p 4005 -h nitro-node" # Set the payment channel id in a variable PAYMENT_CHANNEL_ID= ``` - Check payment channel between A' and C' ```bash laconic-so deployment --dir l2alice-nitro-deployment exec nitro-rpc-client "nitro-rpc-client get-payment-channel $PAYMENT_CHANNEL_ID -p 4005 -h nitro-node" # Expected output: # { # ID: '0xb29aeb32c9495a793ebf7bd116232075d1e7bfe89fc82281c7d498e3ffd3e3bf', # Status: 'Open', # Balance: { # AssetAddress: '', # Payee: '0xa8d2d06ace9c7ffc24ee785c2695678aecdfd7a0', # Payer: '0xaaa6628ec44a8a742987ef3a114ddfe2d4f7adce', # PaidSoFar: 0n, # RemainingFunds: 1000n # } # } ``` - After virtual fund objective is complete, make payments ```bash laconic-so deployment --dir l2alice-nitro-deployment exec nitro-rpc-client "nitro-rpc-client pay $PAYMENT_CHANNEL_ID 200 -p 4005 -h nitro-node" # Expected output: # { # Amount: 200, # Channel: '0xb29aeb32c9495a793ebf7bd116232075d1e7bfe89fc82281c7d498e3ffd3e3bf' # } ``` - Check payment channel status again to view updated channel state - Close payment channel after payments ```bash laconic-so deployment --dir l2alice-nitro-deployment exec nitro-rpc-client "nitro-rpc-client virtual-defund $PAYMENT_CHANNEL_ID -p 4005 -h nitro-node" ``` - Check L2 mirrored channels status after virtual-defund is complete: - Note balance change in A' node: ```bash laconic-so deployment --dir l2alice-nitro-deployment exec nitro-rpc-client "nitro-rpc-client get-all-ledger-channels -p 4005 -h nitro-node" # Expected output: # {"ID":"0x6a9f5ccf1fa802525d794f4a899897f947615f6acc7141e61e056a8bfca29179","Status":"Open","Balance":{"AssetAddress":"","Me":"0xaaa6628ec44a8a742987ef3a114ddfe2d4f7adce","Them":"0xbbb676f9cff8d242e9eac39d063848807d3d1d94","MyBalance":999800,"TheirBalance":1000200},"ChannelMode":"Open"} ``` - Note balance change in C' node: ```bash laconic-so deployment --dir l2charlie-nitro-deployment exec nitro-rpc-client "nitro-rpc-client get-all-ledger-channels -p 4005 -h nitro-node" # Expected output: # {"ID":"0x15dbe6b996e4e46fdd6ea3e2074cbca58014dbb07368e3e7ba286df5c7b9da0d","Status":"Open","Balance":{"AssetAddress":"","Me":"0xa8d2d06ace9c7ffc24ee785c2695678aecdfd7a0","Them":"0xbbb676f9cff8d242e9eac39d063848807d3d1d94","MyBalance":1000200,"TheirBalance":999800},"ChannelMode":"Open"} ``` ## Demo cleanup - Reset nitro-node deployments: - Stop nitro-node deployments and remove volumes: ```bash # Run where deployments are created laconic-so deployment --dir l1alice-nitro-deployment stop --delete-volumes laconic-so deployment --dir l1charlie-nitro-deployment stop --delete-volumes laconic-so deployment --dir l2alice-nitro-deployment stop --delete-volumes laconic-so deployment --dir l2charlie-nitro-deployment stop --delete-volumes ``` - Clear nitro-node deployments: ```bash # Run where deployments are created sudo rm -rf l1alice-nitro-deployment sudo rm -rf l1charlie-nitro-deployment sudo rm -rf l2alice-nitro-deployment sudo rm -rf l2charlie-nitro-deployment ``` - Reset wallet: - In laconic-wallet, click on the `Reset Wallet` button to disconnect all apps and clear the accounts - Reset stage 0 and stage 1 laconicd deployments: - Stop deployment and remove volumes: ```bash # Run where deployments are created laconic-so deployment --dir stage0-deployment stop --delete-volumes laconic-so deployment --dir stage1-deployment stop --delete-volumes ``` - Remove data from stage 0 and stage 1 deployments: ```bash # Run where deployments are created sudo rm -rf 'stage0-deployment/data/laconicd-data/*' sudo rm -rf 'stage0-deployment/data/genesis-config/*' sudo rm -rf 'stage1-deployment/data/laconicd-data/*' sudo rm -rf 'stage1-deployment/data/genesis-config/*' ``` - Reset faucet deployment: - Stop deployment and remove volumes: ```bash laconic-so deployment --dir laconic-faucet-deployment stop --delete-volumes ``` - Remove data from the deployment ```bash # Run where deployments are created sudo rm -rf 'laconic-faucet-deployment/data/faucet-data/*' ``` ## Re-run - After running demo cleanup, follow the steps from [Demo](#demo) to re-run the demo ## Cleanup - Reset nitro-node deployments: - Stop nitro-node deployments and remove volumes: ```bash # Run where deployments are created laconic-so deployment --dir l1alice-nitro-deployment stop --delete-volumes laconic-so deployment --dir l1charlie-nitro-deployment stop --delete-volumes laconic-so deployment --dir l2alice-nitro-deployment stop --delete-volumes laconic-so deployment --dir l2charlie-nitro-deployment stop --delete-volumes laconic-so deployment --dir bridge-deployment stop --delete-volumes ``` - Clear nitro-node and bridge deployments: ```bash # Run where deployments are created sudo rm -rf l1alice-nitro-deployment sudo rm -rf l1charlie-nitro-deployment sudo rm -rf l2alice-nitro-deployment sudo rm -rf l2charlie-nitro-deployment sudo rm -rf bridge-deployment ``` - Reset wallet and stop the app: - In laconic-wallet, click on the `Reset Wallet` button to disconnect all apps and clear the accounts - Stop (`Ctrl+C`) both `laconic-wallet` and `testnet-onboarding-app` - Clean up stage 0 and stage 1 laconicd deployments: - Stop deployment and remove volumes: ```bash # Run where deployments are created laconic-so deployment --dir stage0-deployment stop --delete-volumes laconic-so deployment --dir stage1-deployment stop --delete-volumes ``` - Clear deployments: ```bash # Run where deployments are created sudo rm -rf stage0-deployment sudo rm -rf stage1-deployment ``` - Clean up faucet deployment: - Stop deployment and remove volumes: ```bash laconic-so deployment --dir laconic-faucet-deployment stop --delete-volumes ``` - Clear deployment ```bash # Run where deployment is created sudo rm -rf laconic-faucet-deployment ``` - Clean up L1 and L2 deployments: - Stop deployment and remove volumes: ```bash # Run where deployments are created laconic-so deployment --dir fixturenet-optimism-deployment stop --delete-volumes laconic-so deployment --dir fixturenet-eth-deployment stop --delete-volumes ``` - Clear deployments: ```bash # Run where deployments are created sudo rm -rf fixturenet-optimism-deployment sudo rm -rf fixturenet-eth-deployment ``` ## Troubleshooting - If the ledger channel creation fails, follow these steps: - Check whether the status of `cerc/fixturenet-eth-geth` is `unhealthy`. ```bash docker ps ``` - If the chain is not producing new blocks, restart the chain. ```bash laconic-so deployment --dir fixturenet-eth-deployment stop laconic-so deployment --dir fixturenet-eth-deployment start ``` - Stop the nitro-rpc-client direct-fund command if it is stuck - Restart the failed node (for example: to restart Charlie's node) - Stop the failed nitro node ```bash laconic-so deployment --dir l1charlie-nitro-deployment stop ``` - Remove the node's durable store and create it again ```bash sudo rm -rf l1charlie-nitro-deployment/data/nitro_node_data mkdir l1charlie-nitro-deployment/data/nitro_node_data ``` - Restart the node and create ledger channel again ```bash laconic-so deployment --dir l1charlie-nitro-deployment start ``` - Retry the ledger channel creation command