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

Python in local network deployment and tests #20

Merged
merged 36 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
03896c6
Deploy on Python (WIP)
vsuharnikov Sep 24, 2024
7fe81c6
Fixes
vsuharnikov Sep 25, 2024
34aac8a
Asserts in tests
vsuharnikov Sep 25, 2024
0921ad5
Fix
vsuharnikov Sep 25, 2024
493946a
Fix
vsuharnikov Sep 25, 2024
0009726
Remove the setup directory
vsuharnikov Sep 25, 2024
10ee93b
Updated README.md
vsuharnikov Sep 25, 2024
6c70ae4
Test with multiple e2c transfers
vsuharnikov Sep 25, 2024
7640030
Test with multiple c2e transfers
vsuharnikov Sep 26, 2024
e7560a9
Fixed transfer-c2e.py balances comparison
vsuharnikov Sep 26, 2024
801552d
Cleanup
vsuharnikov Sep 26, 2024
7ac7131
Cleanup
vsuharnikov Sep 26, 2024
052caf7
BaseTransfer
vsuharnikov Sep 26, 2024
57cb51c
Renaming
vsuharnikov Sep 26, 2024
30fd707
Up
vsuharnikov Sep 26, 2024
29ac45f
Logs in file
vsuharnikov Sep 26, 2024
c54bd5e
Force Accounts to depend on Network to guarantee right network addres…
vsuharnikov Sep 26, 2024
bca8e78
Up
vsuharnikov Sep 26, 2024
aab750f
pyproject.toml instead of setup.py
vsuharnikov Sep 27, 2024
fcf6d72
Test accounts instead of miners
vsuharnikov Sep 27, 2024
6914dd3
Moving functions to unit0-examples, better logs
vsuharnikov Sep 27, 2024
a6b5e3f
Accounts in ExtendedNetwork
vsuharnikov Sep 27, 2024
90525aa
Decimals instead of float, logs improvements
vsuharnikov Sep 27, 2024
ee96e95
Removed files
vsuharnikov Sep 27, 2024
ba9219e
Fixes
vsuharnikov Sep 30, 2024
5d106b1
Issue and transfer chain contract tokens to run tests in any order
vsuharnikov Sep 30, 2024
9c651d6
Run basic tests
vsuharnikov Oct 1, 2024
05007d6
Fixed tests
vsuharnikov Oct 1, 2024
369d5f5
local-network: removed logs directory, run test with docker compose p…
vsuharnikov Oct 2, 2024
d78da29
Up
vsuharnikov Oct 2, 2024
ef95673
Logging from unit0-examples
vsuharnikov Oct 2, 2024
e442f55
Test improvements
vsuharnikov Oct 2, 2024
40fbd8a
Docker compose context for BlockScout
vsuharnikov Oct 2, 2024
0fdcbde
Merge github/main
vsuharnikov Oct 2, 2024
38bb073
Fix
vsuharnikov Oct 2, 2024
aab9817
Review fixes
vsuharnikov Oct 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions local-network/configs/wavesnode/genesis-template.conf
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,22 @@ genesis-generator {
# Address: 3FSrRN8X7cDsLyYTScS8Yf8KSwZgJBwf1jU
{ seed-text = "devnet-2", nonce = 0, amount = 998036000000000 }

# Additional address
# Seed text: devnet-3
# Additional addresses

# Seed text: devnet-0
Copy link
Contributor Author

Choose a reason for hiding this comment

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

devnet-0 so devnet-3 can be a miner

# Nonce: 0
# Seed: HnyGuCEnV1C
# Private account key: 6xx38JtyDrCBUox2HZ1F6qPZYcFHnfkYQzHRvs3wyRfH
# Public account key: 4rfG6p3Ep2dUr4QqWtJwDvy3ySumMejgTE5sdJLzB756
# Address: 3Fkh3dNmLS6NQtVbHcrADegwLo9DviBL5Ro
{ seed-text = "devnet-3", nonce = 0, amount = 4611685988427387903 }
# Seed: HnyGuCEnV19
# Private account key: 8aYKVCJVYfcSQeSH1kM4D2e4Fcj5cAQzMh8uZ5hW2tB9
# Public account key: GRKksNikCNXYT7HqxCnqzjP5pf4NctgtTnmCvCMDEhAT
# Address: 3Ffcu52v7ETMAFhNAqQvHsv4JuQjEVP9q6E
{ seed-text = "devnet-0", nonce = 0, amount = 2305842994213693951 }

# Seed text: devnet-0
# Nonce: 1
# Seed: HnyGuCEnV19
# Private account key: 5tE8jwZ3B4eLTvdz7LqEBMcmspoqXD9nPCEfcZgh2BeV
# Public account key: BArfnBGQ9gkNHC2EftXf42uJuBioSffZiJoyYCTtwxof
# Address: 3FQFFWxMCDmyZhkRzKA7QiAZL4RKMhJvFnu
{ seed-text = "devnet-0", nonce = 1, amount = 2305842994213693952 }
]
}
6 changes: 4 additions & 2 deletions local-network/deploy/.dockerignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
node_modules
logs
.venv/
.solc-select/
__pycache__/
*.egg-info/
10 changes: 6 additions & 4 deletions local-network/deploy/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
node_modules
logs
.solc-select
**/*.js
.venv/
.solc-select/
__pycache__/
build/
setup/
*.egg-info/
17 changes: 10 additions & 7 deletions local-network/deploy/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
FROM node:18-slim
FROM python:3.12-slim

RUN apt-get update && apt-get install -y --no-install-recommends \
python3 \
python3-pip \
curl \
&& pip3 install solc-select --break-system-packages \
git \
gcc \
libc6-dev \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

WORKDIR /home/node/app
COPY package.json package-lock.json /home/node/app/
RUN npm i
WORKDIR /usr/src/app

COPY local/__init__.py ./local/
COPY pyproject.toml ./

RUN pip install --no-cache-dir --editable .

CMD ["/bin/bash", "deploy-run.sh"]
8 changes: 4 additions & 4 deletions local-network/deploy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ To re-deploy from a container run the following command from the project's root
./deploy-run.sh
```

To run tests (from this directory):
```bash
npm test ./test/transfer-e2c.ts
```
To run tests on the host machine, from this directory:
1. If you're on macOS with Apple Silicon: install `gcc`.
2. Create the virtual environment and install dependencies: `./dev-setup.sh`
3. Run test, e.g.: `./tests/transfer-c2e.py`
2 changes: 0 additions & 2 deletions local-network/deploy/bridge-compile.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ DIR="$(cd "$(dirname "$0")" && pwd)"
cd "${DIR}" || exit

SOLC_VERSION=0.8.26
export VIRTUAL_ENV="${DIR}" # for solc-select and solc

solc-select use $SOLC_VERSION --always-install

echo "Compile bridge.sol"
Expand Down
11 changes: 0 additions & 11 deletions local-network/deploy/common-settings-show.ts

This file was deleted.

2 changes: 1 addition & 1 deletion local-network/deploy/deploy-run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ DIR="$(cd "$(dirname "$0")" && pwd)"
cd "${DIR}" || exit

./bridge-compile.sh
npm run deploy
python -B deploy.py
71 changes: 71 additions & 0 deletions local-network/deploy/deploy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/bin/env python
from time import sleep

from units_network import waves
from units_network.chain_contract import HexStr
from units_network.node import Node

from local.common import configure_script_logger
from local.network import get_local

log = configure_script_logger("main")
network = get_local()


node = Node()
min_peers = len(network.cl_miners) - 1
while True:
r = node.connected_peers()
if len(r) >= min_peers:
break

log.info(f"Wait for {min_peers} peers, now: {r}")
sleep(2)

log.info(f"Chain contract address: {network.cl_chain_contract.oracleAddress}")

script_info = network.cl_chain_contract.oracleAcc.scriptInfo()
if script_info["script"] is None:
log.info("Set chain contract script")

with open("setup/waves/main.ride", "r", encoding="utf-8") as file:
source = file.read()
r = network.cl_chain_contract.setScript(source)
waves.force_success(log, r, "Can not set the chain contract script")

if not network.cl_chain_contract.isContractSetup():
log.info("Call ChainContract.setup")
el_genesis_block = network.w3.eth.get_block(0)

assert "hash" in el_genesis_block
el_genesis_block_hash = HexStr(el_genesis_block["hash"].to_0x_hex())

log.info(f"Genesis block hash: {el_genesis_block_hash}")

r = network.cl_chain_contract.setup(el_genesis_block_hash)
waves.force_success(log, r, "Can not setup the chain contract")


r = network.cl_chain_contract.evaluate("allMiners")
joined_miners = []
for entry in r["result"]["value"]:
joined_miners.append(entry["value"])
log.info(f"Miners: {joined_miners}")

for miner in network.cl_miners:
if miner.account.address not in joined_miners:
log.info(f"Call ChainContract.join by miner f{miner.account.address}")
r = network.cl_chain_contract.join(miner.account, miner.el_reward_address_hex)
waves.force_success(
log,
r,
f"{miner.account.address} can not join the chain contract",
wait=False,
)

while True:
r = network.w3.eth.get_block("latest")
if "number" in r and r["number"] >= 1:
break
log.info("Wait for at least one block on EL")
sleep(3)
2 changes: 0 additions & 2 deletions local-network/deploy/deploy.ts

This file was deleted.

18 changes: 18 additions & 0 deletions local-network/deploy/dev-setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/usr/bin/env bash

if [ ! -d "$PWD/.venv" ]; then
echo "Create a virtual environment"
python3 -m venv .venv --prompt local-network
source .venv/bin/activate

if [[ "$(uname)" == "Darwin" && "$(uname -m)" == "arm64" ]]; then
# Otherwise python-axolotl-curve25519 won't compile
export CC=gcc
fi

echo "Install dependencies"
# --no-cache-dir is useful during development and local units-network in dependencies
pip install --editable .
fi

echo "Done."
Empty file.
74 changes: 74 additions & 0 deletions local-network/deploy/local/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import os
from dataclasses import dataclass
from decimal import Decimal
from functools import cached_property

from eth_account.signers.local import LocalAccount
from pywaves import pw
from units_network import units
from units_network.chain_contract import common_utils
from web3.types import Wei


@dataclass()
class BaseTransfer:
el_account: LocalAccount
cl_account: pw.Address
raw_amount: Decimal

@cached_property
def wei_amount(self) -> Wei:
return units.raw_to_wei(self.raw_amount)

@cached_property
def waves_atomic_amount(self) -> int:
return units.raw_to_waves_atomic(self.raw_amount)


@dataclass()
class C2ETransfer(BaseTransfer):
@property
def from_account(self) -> pw.Address:
return self.cl_account

@property
def to_account(self) -> LocalAccount:
return self.el_account

def __repr__(self) -> str:
return f"C2E(from={self.cl_account.address}, to={self.el_account.address}, {self.raw_amount} UNIT0)"


@dataclass()
class E2CTransfer(BaseTransfer):
@property
def from_account(self) -> LocalAccount:
return self.el_account

@property
def to_account(self) -> pw.Address:
return self.cl_account

def __repr__(self) -> str:
return f"E2C(from={self.el_account.address}, to={self.cl_account.address}, {self.raw_amount} UNIT0)"


_INSIDE_DOCKER = None


def in_docker() -> bool:
global _INSIDE_DOCKER
if _INSIDE_DOCKER is None:
try:
os.stat("/.dockerenv")
_INSIDE_DOCKER = True
except FileNotFoundError:
_INSIDE_DOCKER = False
return _INSIDE_DOCKER


def configure_script_logger(name: str):
file = None
if in_docker():
file = "/var/log/deploy/deploy.log"
return common_utils.configure_script_logger(name, file)
91 changes: 91 additions & 0 deletions local-network/deploy/local/network.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
from dataclasses import dataclass
from functools import cached_property
from typing import List, Optional

from eth_account.signers.local import LocalAccount
from pywaves import pw
from units_network import networks
from units_network.chain_contract import ChainContract, HexStr
from units_network.networks import Network, NetworkSettings
from web3 import Account

from local.common import in_docker


def get_waves_api_url(n: int) -> str:
return f"http://wavesnode-{n}:6869" if in_docker() else f"http://127.0.0.1:{n}6869"


def get_ec_api_url(n: int) -> str:
return f"http://ec-{n}:8545" if in_docker() else f"http://127.0.0.1:{n}8545"


@dataclass
class Miner:
account: pw.Address
el_reward_address_hex: HexStr


class ExtendedNetwork(Network):
@cached_property
def cl_chain_contract(self) -> ChainContract:
return ChainContract(seed="devnet-1", nonce=2)

@cached_property
def cl_miners(self) -> List[Miner]:
return [
Miner(
account=pw.Address(
seed="devnet-1",
nonce=0,
),
el_reward_address_hex=HexStr(
"0x7dbcf9c6c3583b76669100f9be3caf6d722bc9f9"
),
),
Miner(
account=pw.Address(
seed="devnet-2",
nonce=0,
),
el_reward_address_hex=HexStr(
"0xcf0b9e13fdd593f4ca26d36afcaa44dd3fdccbed"
),
),
]

@cached_property
def cl_rich_accounts(self) -> List[pw.Address]:
return [pw.Address(seed="devnet-0", nonce=n) for n in range(0, 2)]

@cached_property
def el_rich_accounts(self) -> List[LocalAccount]:
return [
Account.from_key(
"0x8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63"
),
Account.from_key(
"0xae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f"
),
]


local_net = NetworkSettings(
name="LocalNet",
chain_id_str="D",
cl_node_api_url=get_waves_api_url(1),
el_node_api_url=get_ec_api_url(1),
chain_contract_address="3FdaanzgX4roVgHevhq8L8q42E7EZL9XTQr",
)


_NETWORK: Optional[ExtendedNetwork] = None


def get_local() -> ExtendedNetwork:
global _NETWORK
if _NETWORK is None:
networks.prepare(local_net)
_NETWORK = ExtendedNetwork(local_net)

return _NETWORK
Loading