Run Local Testnet
Overview
In this tutorial, weβre going to set up a development environment. We are going to deploy a full stack of the core blockchain and connect the Web UI to the blockchain. By the end of the tutorial, you will be able to:
- Send confidential Commands and Queries
- Get a ready-to-hack version of Phala Network for building your confidential DApps
A full Phala Network stack has three components, with an optional Javascript SDK. The core components are available at Phala-Network/phala-blockchain:
phala-node
: The Substrate blockchain nodepRuntime
: The TEE runtime. Contracts run inpRuntime
pherry
: The Substrate-TEE bridge relayer. Connects the blockchain andpRuntime
The Javascript SDK is at Phala-Network/js-sdk. The Web UI based on our SDK needs to connect to both the blockchain and the pRuntime
to send Commands and Queries.
Setting up
In this tutorial, we assume the operating system is Ubuntu 22.04. Other Linux distributions should also work, but the instructions or commands may vary. 4 cores and 8GB RAM is the minimal requirement to build the project including the core blockchain.
Deployment Options
There are 2 ways to deploy a local testnet.
- devPHAse or Swanky Phala CLI Tools
- Build from Source (Most time-consuming)
Environment Setup
Make sure to go through the environment setup before continuing.
sudo apt install -y build-essential pkg-config libssl-dev protobuf-compiler
Deploy via devPHAse
In this section, you will deploy your local testnet using the DevPHAse CLI Tool. First, you will need to create a new workspace folder on your system and execute the following:
Install devPHAse and required libs
yarn init
yarn add -D typescript ts-node
yarn add -D @devphase/cli
Init project
yarn devphase init
Your directory will be initiated with all required files and template Flipper contract.
- .devphase/ # devPHAse cache directory
- contracts/ # here you store your contracts
- flipper/ # template Flipper contract
- Cargo.toml # rust project file
- lib.rs # contract source
- scripts/ # scripts which you can all with devPHAse environment
- deploy.ts # sample deployment script
- get-logs.ts # sample demonstrating how to get contract logs
- tests/ # here you store e2e tests for contracts
- flipper/ # flipper related test suite
- flipper.test.ts # flipper tests example
Prepare environment
yarn devphase check
This command will ensure the proper stack (node, pruntime, pherry) is ready to run. Download stack from offical repository. Verify dependencies.
Output:
yarn devphase check
yarn run v1.22.19
$ (...)/node_modules/.bin/devphase check
[StackBinaryDownloader] Creating stack directory
β Checking configuration file
β Check dependencies
β Checking Phala stack binaries
Done in 42.07s.
You will see a new directory called stacks/
has been created
- stacks/ # here all prepared stacks will be stored
- nightly-2024-03-07/ # bases on your configuration it will latest available stack or any specific you choose
- phala-node # node binary
- pherry # pherry binary
- pruntime # pruntime binary
- *.so.* # multiple requried libs
- *.contract # system contracts
Now you are ready to go.
Compile contract
yarn devphase contract compile -c flipper
Output:
yarn devphase contract compile -c flipper
[MultiContractExecutor] Criteria: flipper
[MultiContractExecutor] Matched contracts:
[MultiContractExecutor] flipper
[MultiContractExecutor]
β― flipper
β flipper
Done in 32.49s.
This command will:
- install contract dependencies
- compile contract (only flipper in this case) and save output to ./contracts/flipper/target
- copy contract artificats
- generate typescript bindings which you can use in scripts and tests
New files:
- artifacts/ # here devPHAse will store compiled contract artifacts
- flipper/ # specific contract
- flipper.contract
- flipper.json
- flipper.wasm
- typings/ # here devPHAse will store ts bindings
- Flipper.ts
Run tests
yarn devphase contract test -t flipper
devPHAse in default config will:
- check stack dependencies
- start local stack
- configure local environment (with minimal required deps)
- execute tests
- save logs into files
Output:
yarn devphase contract test -t flipper
[StackBinaryDownloader] Preparing Phala stack release nightly-2024-03-13
β Checking releases directory
β Checking target release binaries
[Test] Global setup start
[Test] Preparing dev stack
[StackManager] Starting stack nightly-2024-03-13
β Start node component
β Start pRuntime component
β Start pherry component
[Test] Init API
[Test] Setup environment
[StackSetupService] Starting stack setup with default version
β Fetch worker info
β Load system contracts
β Register worker [skipped]
β Register gatekeeper
β Upload Pink system code
β Verify cluster
β Create cluster
β Wait for cluster to be ready
β Add worker endpoint
β Create system contract API
[Test] Global setup done
[Test] Starting tests
Flipper
default constructor
β Should be created with proper intial value
β Should be able to flip value (2572ms)
new constructor
β Should be created with proper intial value
[Test] Global teardown start
[Test] Internal clean up
[Test] Stopping stack
[Test] Global teardown done
3 passing (27s)
[StackManager] pherry exited
[StackManager] pruntime exited
[StackManager] node exited
Done in 33.00s.
New directories created for logs.
- logs/ # here devPHAse will store execution logs
- 2024-03-07T16:09:43.421Z/ # single execution
- node.log
- pherry.log
- pruntime.log
- pink_logger.log # if stack setup with logger here all logs will be stored
Running tests this way is nice but only if it is single execution. If you are developing new feature it may be required to continuously test it. In this case default procedure is time-consuming, because setting up stack takes ~40s.
Nothing blocks you from using the same running node for multiple tests.
Long-running local environment
This command will start and keep running all stack components. However, network is not configured yet to accept contracts.
yarn devphase stack run --save-logs
Configure network
Now let's configure the network to enable your local environment to deploy a Phat Contract and collect logs.
yarn devphase stack setup -m 3
Output
yarn devphase stack setup -m 3
[StackSetupService] Starting stack setup with default version
β Fetch worker info
β Load system contracts
β Register worker [skipped]
β Register gatekeeper
β Upload Pink system code
β Verify cluster
β Create cluster
β Wait for cluster to be ready
β Add worker endpoint
β Create system contract API
β Deploy tokenomic driver
β Deploy SideVM driver
β Calculate logger server contract ID
β Prepare chain for logger server
β Deploy logger server
[StackSetup] Stack is ready
[StackSetup] Cluster Id
[StackSetup] 0x0000000000000000000000000000000000000000000000000000000000000001
Done in 38.52s.
Now all required network components should be ready for Phat Contract deployment.
Run tests using long-running local environment
-e
flag will make devPHAse to execute test without setting up temporary stack but using existing one.
yarn devphase contract test -t flipper -e
Output
yarn devphase contract test -t flipper -e
[Test] Global setup start
[Test] Init API
[Test] Setup environment
[StackSetupService] Starting stack setup with default version
β Fetch worker info
β Load system contracts
β Register worker [skipped]
β Register gatekeeper [skipped]
β Upload Pink system code [skipped]
β Verify cluster
β Create cluster [skipped]
β Wait for cluster to be ready
β Add worker endpoint [skipped]
β Create system contract API
[Test] Global setup done
[Test] Starting tests
Flipper
default constructor
β Should be created with proper intial value
Logs from pink server:
#996 TX info Resource uploaded to cluster, by 8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 (5FHneW46...), type=InkCode, hash=0xcbf8151426f6ce308a875a1c5cc6e2a4f4c0bca3be4371a15b0d25bcca336f55
#999 EST info instantiated
#1007 TX info instantiated
β Should be able to flip value (2390ms)
Logs from pink server:
#1009 EST info instantiated
#1021 TX info instantiated
new constructor
β Should be created with proper intial value
Logs from pink server:
#1036 EST info instantiated
#1044 TX info instantiated
[Test] Global teardown start
[Test] Internal clean up
[Test] Global teardown done
3 passing (18s)
Done in 24.33s.
Running scripts
DevPHAse will run script on specified environment. If environment provides a PinkLogger - logs will be saved locally.
Deploy contract script
yarn devphase script scripts/deploy.ts
Output
yarn devphase script scripts/deploy.ts
[Script] Executing /home/hashwarlock/Templates/YarnTest/scripts/deploy.ts
Contract ID: 0x8e132d6bdebe37824b31df98669063d52d25d7eb0c40358c7f0e47876bc8a879
{ Ok: false }
{
Finalized: '0xda06fe993f51260a4bd726d721ae34ec7d1b939cb9a425a0dd4fd9c24831d023'
}
{ Ok: true }
Done in 9.62s.
Get logs locally
Using the contract ID from the previous script
0x8e132d6bdebe37824b31df98669063d52d25d7eb0c40358c7f0e47876bc8a879
modify contractIds variable in scripts/get-logs.ts
then execute the script to get logs.
yarn devphase script scripts/get-logs.ts
Output
yarn devphase script scripts/get-logs.ts
[Script] Executing /home/hashwarlock/Templates/YarnTest/scripts/get-logs.ts
0x8e132d6bdebe37824b31df98669063d52d25d7eb0c40358c7f0e47876bc8a879
[
{
sequence: 50,
type: 'Log',
blockNumber: 1714,
contract: '0x8e132d6bdebe37824b31df98669063d52d25d7eb0c40358c7f0e47876bc8a879',
entry: '0x8e132d6bdebe37824b31df98669063d52d25d7eb0c40358c7f0e47876bc8a879',
execMode: 'transaction',
timestamp: 2024-03-14T05:40:24.365Z,
level: 3,
message: 'instantiated'
},
{
sequence: 55,
type: 'MessageOutput',
blockNumber: 1723,
origin: '0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d',
contract: '0x8e132d6bdebe37824b31df98669063d52d25d7eb0c40358c7f0e47876bc8a879',
nonce: '0xacac9d33a106f1051887b243f82755276d8443c070fb4c9987018674cbbe478b',
output: {
gasConsumed: { refTime: 440059308, proofSize: 67027 },
gasRequired: { refTime: 65728937984, proofSize: 10485760 },
storageDeposit: { charge: 0 },
debugMessage: '',
result: { ok: { flags: [], data: '0x00' } }
}
}
]
Run devPHAse on PoC6 Testnet or Phala Mainnet
You can specify to run commands on any network - including PoC6 Testnet or Phala Mainnet. Check commands help for further details.
Deploy contract command
yarn devphase help contract deploy
Output
Deploy contract
USAGE
$ devphase contract deploy [ARGS] -c <value> -o <value> [-t InkCode|SidevmCode|IndeterministicInkCode] [-n
<value>] [-l <value>] [-a <value>]
ARGUMENTS
ARGS Constructor arguments
FLAGS
-a, --account=<value> [default: alice] Account used to deploy (managed account key)
-c, --contract=<value> (required) Contract name
-l, --cluster=<value> Target cluster Id
-n, --network=<value> [default: local] Target network to deploy (local default)
-o, --ctor=<value> (required) Contract constructor to call (name)
-t, --type=<option> [default: InkCode]
<options: InkCode|SidevmCode|IndeterministicInkCode>
Done in 0.99s.
Call contract command
yarn devphase help contract call
Output
Call contract
USAGE
$ devphase contract call [ARGS] -c <value> -i <value> -m <value> [-t InkCode|SidevmCode|IndeterministicInkCode]
[-a query|tx] [-n <value>] [-l <value>] [-a <value>]
ARGUMENTS
ARGS Call arguments
FLAGS
-a, --accessor=<option> [default: query] Method type: transaction or query
<options: query|tx>
-a, --account=<value> [default: alice] Account used to call (managed account key)
-c, --contract=<value> (required) Contract name
-i, --id=<value> (required) Contract ID
-l, --cluster=<value> Target cluster Id
-m, --method=<value> (required) Contract method to call (name)
-n, --network=<value> [default: local] Target network to deploy (local default)
-t, --type=<option> [default: InkCode]
<options: InkCode|SidevmCode|IndeterministicInkCode>
Done in 1.00s.
Build from Source
The Phala-Network/phala-blockchain repository always contains the latest build instructions, at the time of writing (December 26, 2022), we use the following commands to set up development environment:
# First clone the repository
git clone https://github.com/Phala-Network/phala-blockchain.git
# Change to the repository directory
cd phala-blockchain
# Install system dependencies:
sudo apt install -y build-essential pkg-config libssl-dev protobuf-compiler
# Install Rust
curl https://sh.rustup.rs -sSf | sh
# Install dependencies for Substrate development
git submodule update --init
sh ./scripts/init.sh
# Installl LLVM 14
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
./llvm.sh 14
Then run the following command to build the Phala blockchain:
cargo build --release
It takes approximately 20 minutes to complete the building process on a laptop equipped with an AMD Ryzen 7 4700U processor with 8 cores, 8 threads, and 32GB of RAM.
Start the local testnet
We have a dedicate set of scripts to get the blockchain to run, checkout out this page for full details. For simplicity we can start as simple as follows:
We might want to clean up runtime data to have to clean starting environment, from the root of the phala-blockchain
project, run this to clean things up:
./scripts/run/clear-pruntime.sh
Then go ahead and run these 3 commands in 3 separate terminals:
./scripts/run/node.sh
./scripts/run/pruntime.sh
./scripts/run/pherry.sh
Now you have a full node at ws://localhost:19944, and the pruntime is at http://localhost:18000.
After you start the node and the pruntime, you need set up Phat Contract environment once. This can be done with our phala-blockchain-setup repo:
git clone https://github.com/shelvenzhou/phala-blockchain-setup.git
cd phala-blockchain-setup
yarn
ENDPOINT=ws://localhost:19944 \
WORKERS=http://localhost:18000 \
GKS=http://localhost:18000 \
yarn setup:drivers
After all, you testnet is ready. You can continue with the Connect the polkadot app to the local testnet section.
By default you get the Phala blockchain node at ws://localhost:9944 and the pruntime at http://localhost:8000, you can change the configuration at devphase.config.ts
, for more details check out the devPHAse repository
Connect the Phat UI to the local testnet
We have a client-side application at https://phat.phala.network/, you can follow the instructions that connect the application to the local testnet.
** TODO add Diagram**
As the above figure shows, we first click the green dot at the upper-right cornor to set the RPC Endpoint
to ws://localhost:19944
, or ws://localhost:9944
if you start the chain via the devPHAse approach, and change the PRuntime field accordingly.
Donβt forget to claim some Test-PHA
s, theyβre required to deploy Phat Contracts and send transactions.
Connect the polkadot app to the local testnet
Open up https://polkadot.js.org/apps, click the upper-left corner to call forth the endpoint setup menu:
** TODO add Diagram **
Set the field custom endpoint
to ws://localhost:9944
and then click the switch
button to connect to it.
Congratulations! Now you have a fully qualified local development environment!