Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 10 additions & 1 deletion .github/workflows/contract-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,20 @@ jobs:
sudo DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt-get update
sudo DEBIAN_FRONTEND=noninteractive NEEDRESTART_MODE=a apt-get install -y --no-install-recommends -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" build-essential clang curl libssl-dev llvm libudev-dev protobuf-compiler nodejs pkg-config

- name: Build node-subtensor and Ink contracts
run: |
cd ${{ github.workspace }}
rustup component add rust-src
cargo install cargo-contract
cargo build --release -p node-subtensor --features fast-runtime
cd contract-tests/bittensor
cargo contract build --release

- name: Run tests
uses: nick-fields/retry@v3
with:
timeout_minutes: 90
max_attempts: 3
max_attempts: 5
retry_wait_seconds: 60
command: |
cd ${{ github.workspace }}
Expand Down
20 changes: 5 additions & 15 deletions contract-tests/run-ci.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,10 @@

echo "start run-ci.sh"

cd contract-tests

cd bittensor

rustup component add rust-src
cargo install cargo-contract
cargo contract build --release

cd ../..

scripts/localnet.sh &>/dev/null &
target/release/node-subtensor --dev --tmp --one &>/dev/null &

i=1
while [ $i -le 2000 ]; do
while [ $i -le 60 ]; do
if nc -z localhost 9944; then
echo "node subtensor is running after $i seconds"
break
Expand All @@ -25,11 +15,11 @@ while [ $i -le 2000 ]; do
done

# port not available exit with error
if [ "$i" -eq 2000 ]; then
if [ "$i" -eq 60 ]; then
exit 1
fi

sleep 10
sleep 2

if ! nc -z localhost 9944; then
echo "node subtensor exit, port not available"
Expand All @@ -43,7 +33,7 @@ npm i -g polkadot-api

bash get-metadata.sh

sleep 5
sleep 2

yarn install --frozen-lockfile

Expand Down
1 change: 0 additions & 1 deletion contract-tests/src/substrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ export async function getTransactionWatchPromise(tx: Transaction<{}, string, str

// TODO investigate why finalized not for each extrinsic
if (value.type === "finalized") {
console.log("Transaction is finalized in block:", value.txHash);
subscription.unsubscribe();
clearTimeout(timeoutId);
if (!value.ok) {
Expand Down
26 changes: 23 additions & 3 deletions contract-tests/src/subtensor.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import * as assert from "assert";
import { devnet, MultiAddress } from '@polkadot-api/descriptors';
import { TypedApi, TxCallData, Binary, Enum } from 'polkadot-api';
import { TypedApi, TxCallData, Binary, Enum, getTypedCodecs } from 'polkadot-api';
import { KeyPair } from "@polkadot-labs/hdkd-helpers"
import { getAliceSigner, waitForTransactionCompletion, getSignerFromKeypair, waitForTransactionWithRetry } from './substrate'
import { convertH160ToSS58, convertPublicKeyToSs58, ethAddressToH160 } from './address-utils'
import { tao } from './balance-math'
import internal from "stream";

// create a new subnet and return netuid
export async function addNewSubnetwork(api: TypedApi<typeof devnet>, hotkey: KeyPair, coldkey: KeyPair) {
Expand All @@ -26,6 +25,8 @@ export async function addNewSubnetwork(api: TypedApi<typeof devnet>, hotkey: Key
const newTotalNetworks = await api.query.SubtensorModule.TotalNetworks.getValue()
// could create multiple subnetworks during retry, just return the first created one
assert.ok(newTotalNetworks > totalNetworks)
// reset network last lock to 0 for tests
await resetNetworkLastLock(api)
return totalNetworks
}

Expand Down Expand Up @@ -398,4 +399,23 @@ export async function sendWasmContractExtrinsic(api: TypedApi<typeof devnet>, co
storage_deposit_limit: BigInt(1000000000)
})
await waitForTransactionWithRetry(api, tx, signer)
}
}

// Reset network last lock to 0 for tests, then the cose for network registration will be the default minimum
// We can make the const cost for each network registration for tests. avoid the cost spike
export async function resetNetworkLastLock(api: TypedApi<typeof devnet>) {
const alice = getAliceSigner()
const key = await api.query.SubtensorModule.NetworkLastLockCost.getKey()

// Get the codec for NetworkLastLockCost value (TaoCurrency/u128)
const codec = await getTypedCodecs(devnet)
const valueCodec = codec.query.SubtensorModule.NetworkLastLockCost.value

// Encode the value 0 as SCALE-encoded bytes
const encodedValue = valueCodec.enc(BigInt(0))

const changes: [Binary, Binary][] = [[Binary.fromHex(key.toString()), Binary.fromBytes(encodedValue)]];
const internalCall = api.tx.System.set_storage({ items: changes })
const tx = api.tx.Sudo.sudo({ call: internalCall.decodedCall })
await waitForTransactionWithRetry(api, tx, alice)
}
2 changes: 1 addition & 1 deletion contract-tests/test/alphaPool.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { ethers } from "ethers"
import { tao } from "../src/balance-math";
import { ISTAKING_V2_ADDRESS, IStakingV2ABI } from "../src/contracts/staking";
// import { KeyPair } from "@polkadot-labs/hdkd-helpers";
describe("bridge token contract deployment", () => {
describe("Alpha Pool Test", () => {
// init eth part
const wallet = generateRandomEthersWallet();
let publicClient: PublicClient;
Expand Down
21 changes: 13 additions & 8 deletions contract-tests/test/leasing.precompile.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ethers } from "ethers";
import { TypedApi } from "polkadot-api";
import { devnet } from "@polkadot-api/descriptors";
import { getAliceSigner, getBobSigner, getDevnetApi, waitForFinalizedBlock } from "../src/substrate";
import { forceSetBalanceToEthAddress } from "../src/subtensor";
import { forceSetBalanceToEthAddress, resetNetworkLastLock } from "../src/subtensor";
import { decodeAddress } from "@polkadot/util-crypto";
import { u8aToHex } from "@polkadot/util";
import { ILEASING_ADDRESS, ILeasingABI } from "../src/contracts/leasing";
Expand All @@ -24,6 +24,8 @@ describe("Test Leasing precompile", () => {
let leaseContract: ethers.Contract;
let crowdloanContract: ethers.Contract;
let neuronContract: ethers.Contract;
const crowdloanDeposit = BigInt(100_000_000_000);
let crowdloanCap: bigint;

const alice = getAliceSigner();
const bob = getBobSigner();
Expand All @@ -40,12 +42,19 @@ describe("Test Leasing precompile", () => {

await forceSetBalanceToEthAddress(api, wallet1.address);
await forceSetBalanceToEthAddress(api, wallet2.address);

await resetNetworkLastLock(api);
const minLockCost = await api.query.SubtensorModule.NetworkMinLockCost.getValue();
// guarantee that the crowdloan cap is larger than the deposit
if (minLockCost > crowdloanDeposit) {
crowdloanCap = minLockCost * BigInt(2);
} else {
crowdloanCap = crowdloanDeposit * BigInt(2);
}
});

it("gets an existing lease created on substrate side, its subnet id and its contributor shares", async () => {
const nextCrowdloanId = await api.query.Crowdloan.NextCrowdloanId.getValue();
const crowdloanDeposit = BigInt(100_000_000_000); // 100 TAO
const crowdloanCap = await api.query.SubtensorModule.NetworkLastLockCost.getValue() * BigInt(2);
const crowdloanEnd = await api.query.System.Number.getValue() + 100;
const leaseEmissionsShare = 15;
const leaseEnd = await api.query.System.Number.getValue() + 300;
Expand All @@ -67,8 +76,8 @@ describe("Test Leasing precompile", () => {
amount: crowdloanCap - crowdloanDeposit,
}).signAndSubmit(bob);

await waitForFinalizedBlock(api, crowdloanEnd);

await waitForFinalizedBlock(api, crowdloanEnd);
const nextLeaseId = await api.query.SubtensorModule.NextSubnetLeaseId.getValue();
await api.tx.Crowdloan.finalize({ crowdloan_id: nextCrowdloanId }).signAndSubmit(alice);

Expand Down Expand Up @@ -98,9 +107,7 @@ describe("Test Leasing precompile", () => {

it("registers a new leased network through a crowdloan and retrieves the lease", async () => {
const nextCrowdloanId = await api.query.Crowdloan.NextCrowdloanId.getValue();
const crowdloanDeposit = BigInt(100_000_000_000); // 100 TAO
const crowdloanMinContribution = BigInt(1_000_000_000); // 1 TAO
const crowdloanCap = await api.query.SubtensorModule.NetworkLastLockCost.getValue() * BigInt(2);
const crowdloanEnd = await api.query.System.Number.getValue() + 100;
const leasingEmissionsShare = 15;
const leasingEndBlock = await api.query.System.Number.getValue() + 300;
Expand Down Expand Up @@ -159,9 +166,7 @@ describe("Test Leasing precompile", () => {
await tx.wait();

const nextCrowdloanId = await api.query.Crowdloan.NextCrowdloanId.getValue();
const crowdloanDeposit = BigInt(100_000_000_000); // 100 TAO
const crowdloanMinContribution = BigInt(1_000_000_000); // 1 TAO
const crowdloanCap = await api.query.SubtensorModule.NetworkLastLockCost.getValue() * BigInt(2);
const crowdloanEnd = await api.query.System.Number.getValue() + 100;
const leasingEmissionsShare = 15;
const leasingEndBlock = await api.query.System.Number.getValue() + 200;
Expand Down
6 changes: 3 additions & 3 deletions contract-tests/test/staking.precompile.full-limit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ describe("Test staking precompile add remove limit methods", () => {
IStakingV2ABI,
wallet1,
);

await new Promise(resolve => setTimeout(resolve, 1000));
const tx = await contract.addStakeLimit(
hotkey.publicKey,
tao(2000),
Expand Down Expand Up @@ -131,7 +131,7 @@ describe("Test staking precompile add remove limit methods", () => {
IStakingV2ABI,
wallet2,
);

await new Promise(resolve => setTimeout(resolve, 1000));
const tx = await contract.addStakeLimit(
hotkey.publicKey,
tao(2000),
Expand Down Expand Up @@ -165,7 +165,7 @@ describe("Test staking precompile add remove limit methods", () => {
IStakingV2ABI,
wallet2,
);

await new Promise(resolve => setTimeout(resolve, 1000));
const tx = await contract.removeStakeFull(
hotkey.publicKey,
netuid,
Expand Down
6 changes: 6 additions & 0 deletions contract-tests/test/staking.precompile.wrap.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { ethers } from "ethers";
import { generateRandomEthersWallet } from "../src/utils";

import { abi, bytecode } from "../src/contracts/stakeWrap";
import { setMaxIdleHTTPParsers } from "http";

describe("Test staking precompile add from deployed contract", () => {
const hotkey = getRandomSubstrateKeypair();
Expand Down Expand Up @@ -62,19 +63,24 @@ describe("Test staking precompile add from deployed contract", () => {
const txResponse = await wallet1.sendTransaction(ethTransfer)
await txResponse.wait();

console.log("stakeWrap contract deployed, target: ", contract.target.toString());

const deployedContract = new ethers.Contract(
contract.target.toString(),
abi,
wallet1,
);

await new Promise(resolve => setTimeout(resolve, 1000));
const tx = await deployedContract.stake(
hotkey.publicKey,
netuid,
tao(2),
);
await tx.wait();

await new Promise(resolve => setTimeout(resolve, 1000));

const tx2 = await deployedContract.removeStake(
hotkey.publicKey,
netuid,
Expand Down
4 changes: 4 additions & 0 deletions contract-tests/test/subnet.precompile.hyperparameter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ describe("Test the Subnet precompile contract", () => {
await disableAdminFreezeWindowAndOwnerHyperparamRateLimit(api)
})

beforeEach(async () => {
await new Promise(resolve => setTimeout(resolve, 500))
})

it("Can register network without identity info", async () => {
const totalNetwork = await api.query.SubtensorModule.TotalNetworks.getValue()

Expand Down
2 changes: 1 addition & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
// `spec_version`, and `authoring_version` are the same between Wasm and native.
// This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use
// the compatible custom types.
spec_version: 363,
spec_version: 364,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
Expand Down
Loading