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

custom errors signed extension #700

Merged
merged 18 commits into from
Aug 16, 2024
Merged
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
2 changes: 1 addition & 1 deletion CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* @sacha-l @lisa-parity
* @unconst
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ Requirements:

## For Subnet Development

If you are developing and testing subnet incentive mechanism, you will need to run a local subtensor node. Follow the detailed step-by-step instructions provided in the document [Running subtensor locally](./docs/running-subtensor-locally.md) to run either a lite node or an archive node. Also see the [**Subtensor Nodes** section in Bittensor Developer Documentation](https://docs.bittensor.com/subtensor-nodes).
If you are developing and testing subnet incentive mechanism, you will need to run a local subtensor node. Follow the detailed step-by-step instructions provided in the [**Subtensor Nodes** section in Bittensor Developer Documentation](https://docs.bittensor.com/subtensor-nodes).

### Lite node vs Archive node

Expand Down
205 changes: 1 addition & 204 deletions docs/running-subtensor-locally.md
Original file line number Diff line number Diff line change
@@ -1,206 +1,3 @@
# Running subtensor node locally

- [Method 1: Using Docker](#method-1-using-docker)
- [Method 2: Using Source Code](#method-2-using-source-code)
- [Running on Cloud](#running-on-cloud)

## Method 1: Using Docker

To run a subtensor node with Docker, follow the below steps.

If you are already running a subtensor node using Docker, then go directly to [Step 5 Prepare to Run](#step-5-prepare-to-run) to restart the Docker container. The below steps 1 through 4 are for first time users only.

### Step 1: Install git

Make sure you installed `git` on your machine. See [GitHub docs](https://docs.github.com/en/get-started).

### Step 2: Install Docker

Follow Docker's [official installation guides](https://docs.docker.com/engine/install/) and install Docker.

**Run Docker first**
Before you proceed, make sure that Docker is running.

### Step 3: Clone the subtensor repo

Clone the subtensor repo:

```bash
git clone https://github.com/opentensor/subtensor.git
```

### Step 4: Go into subtensor directory

Then `cd` into the subtensor directory:

```bash
cd subtensor
```

### Step 5: Prepare to run

Execute the below three commands in this order:

Make sure you are on the `main` branch. If not, switch to it:

```bash
git checkout main
```

Pull the latest `main` branch contents:

```bash
git pull
```

Stop the currently running Docker containers:

```bash
docker compose down --volumes
```

### Run a lite node on mainchain

To run a lite node connected to the Bittensor mainchain, run the below command.

```bash
sudo ./scripts/run/subtensor.sh -e docker --network mainnet --node-type lite
```

### Run an archive node on mainchain

To run an archive node connected to the Bittensor mainchain, run the below command.

```bash
sudo ./scripts/run/subtensor.sh -e docker --network mainnet --node-type archive
```

### Run a lite node on testchain

To run a lite node connected to the Bittensor testchain, run the below command.

```bash
sudo ./scripts/run/subtensor.sh -e docker --network testnet --node-type lite
```

### Run an archive node on testchain

To run an archive node connected to the Bittensor testchain, run the below command.

```bash
sudo ./scripts/run/subtensor.sh -e docker --network testnet --node-type archive
```

---

## Method 2: Using Source Code

To install and run a subtensor node by compiling the source code, follow the below steps.

## Install basic packages

Install the basic requirements by running the below commands on a Linux terminal.

```bash title="On Linux"
sudo apt-get update
sudo apt install build-essential
sudo apt-get install clang
sudo apt-get install curl
sudo apt-get install git
sudo apt-get install make
sudo apt install --assume-yes git clang curl libssl-dev protobuf-compiler
sudo apt install --assume-yes git clang curl libssl-dev llvm libudev-dev make protobuf-compiler
```

## Install Rust

Next, install Rust and update the environment by running the following commands:

```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source ~/.cargo/env
```

Next, install Rust toolchain:

```bash
rustup default stable
rustup update
rustup target add wasm32-unknown-unknown
rustup toolchain install nightly
rustup target add --toolchain nightly wasm32-unknown-unknown
```

## Compile subtensor code

Next, to compile the subtensor source code, follow the below steps:

Clone the subtensor repo:

```bash
git clone https://github.com/opentensor/subtensor.git
```

`cd` into the subtensor directory:

```bash
cd subtensor
```

Make sure you are on the `main` branch. If not, switch to it:

```bash
git checkout main
```

Remove previous chain state:

```bash
rm -rf /tmp/blockchain
```

Install subtensor by compiling with `cargo`:

```bash
cargo build --profile production --features=runtime-benchmarks
```

## Run the subtensor node

You can now run the public subtensor node either as a lite node or as an archive node. See below:

### Lite node on mainchain

To run a lite node connected to the mainchain, execute the below command (note the `--sync=warp` flag which runs the subtensor node in lite mode):

```bash title="With --sync=warp setting, for lite node"
./target/production/node-subtensor --chain raw_spec.json --base-path /tmp/blockchain --sync=warp --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /ip4/13.58.175.193/tcp/30333/p2p/12D3KooWDe7g2JbNETiKypcKT1KsCEZJbTzEHCn8hpd4PHZ6pdz5 --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external
```

### Archive node on mainchain

To run an archive node connected to the mainchain, execute the below command (note the `--sync=full` which syncs the node to the full chain and `--pruning archive` flags, which disables the node's automatic pruning of older historical data):

```bash title="With --sync=full and --pruning archive setting, for archive node"
./target/production/node-subtensor --chain raw_spec.json --base-path /tmp/blockchain --sync=full --pruning archive --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /ip4/13.58.175.193/tcp/30333/p2p/12D3KooWDe7g2JbNETiKypcKT1KsCEZJbTzEHCn8hpd4PHZ6pdz5 --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external
```

### Lite node on testchain

To run a lite node connected to the testchain, execute the below command:

```bash title="With bootnodes set to testnet and --sync=warp setting, for lite node."
./target/production/node-subtensor --chain raw_testspec.json --base-path /tmp/blockchain --sync=warp --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /dns/bootnode.test.finney.opentensor.ai/tcp/30333/p2p/12D3KooWPM4mLcKJGtyVtkggqdG84zWrd7Rij6PGQDoijh1X86Vr --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external
```

### Archive node on testchain

To run an archive node connected to the testchain, execute the below command:

```bash title="With bootnodes set to testnet and --sync=full and --pruning archive setting, for archive node"
./target/production/node-subtensor --chain raw_testspec.json --base-path /tmp/blockchain --sync=full --pruning archive --port 30333 --max-runtime-instances 32 --rpc-max-response-size 2048 --rpc-cors all --rpc-port 9944 --bootnodes /dns/bootnode.test.finney.opentensor.ai/tcp/30333/p2p/12D3KooWPM4mLcKJGtyVtkggqdG84zWrd7Rij6PGQDoijh1X86Vr --no-mdns --in-peers 8000 --out-peers 8000 --prometheus-external --rpc-external
```

## Running on cloud

We have not tested these installation scripts on any cloud service. In addition, if you are using Runpod cloud service, then note that this service is already [containerized](https://docs.runpod.io/pods/overview). Hence, the only option available to you is to compile from the source, as described in the above [Method 2: Using Source Code](#method-2-using-source-code) section. Note that these scripts have not been tested on Runpod.
See the [**Subtensor Nodes** section in Bittensor Developer Documentation](https://docs.bittensor.com/subtensor-nodes).
10 changes: 5 additions & 5 deletions pallets/subtensor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1281,7 +1281,7 @@ where
..Default::default()
})
} else {
Err(InvalidTransaction::Call.into())
Err(InvalidTransaction::Custom(1).into())
}
}
Some(Call::reveal_weights { netuid, .. }) => {
Expand All @@ -1293,7 +1293,7 @@ where
..Default::default()
})
} else {
Err(InvalidTransaction::Call.into())
Err(InvalidTransaction::Custom(2).into())
}
}
Some(Call::set_weights { netuid, .. }) => {
Expand All @@ -1305,7 +1305,7 @@ where
..Default::default()
})
} else {
Err(InvalidTransaction::Call.into())
Err(InvalidTransaction::Custom(3).into())
}
}
Some(Call::set_root_weights { netuid, hotkey, .. }) => {
Expand All @@ -1317,7 +1317,7 @@ where
..Default::default()
})
} else {
Err(InvalidTransaction::Call.into())
Err(InvalidTransaction::Custom(4).into())
}
}
Some(Call::add_stake { .. }) => Ok(ValidTransaction {
Expand All @@ -1336,7 +1336,7 @@ where
if registrations_this_interval >= (max_registrations_per_interval.saturating_mul(3))
{
// If the registration limit for the interval is exceeded, reject the transaction
return InvalidTransaction::ExhaustsResources.into();
return Err(InvalidTransaction::Custom(5).into());
}
Ok(ValidTransaction {
priority: Self::get_priority_vanilla(),
Expand Down
7 changes: 2 additions & 5 deletions pallets/subtensor/tests/registration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ fn test_registration_rate_limit_exceeded() {
let result = extension.validate(&who, &call.into(), &info, 10);

// Expectation: The transaction should be rejected
assert_err!(result, InvalidTransaction::ExhaustsResources);
assert_err!(result, InvalidTransaction::Custom(5));

let current_registrants = SubtensorModule::get_registrations_this_interval(netuid);
assert!(current_registrants <= max_registrants);
Expand Down Expand Up @@ -360,10 +360,7 @@ fn test_burned_registration_rate_limit_exceeded() {
extension.validate(&who, &call_burned_register.into(), &info, 10);

// Expectation: The transaction should be rejected
assert_err!(
burned_register_result,
InvalidTransaction::ExhaustsResources
);
assert_err!(burned_register_result, InvalidTransaction::Custom(5));

let current_registrants = SubtensorModule::get_registrations_this_interval(netuid);
assert!(current_registrants <= max_registrants);
Expand Down
66 changes: 63 additions & 3 deletions pallets/subtensor/tests/weights.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ fn test_set_rootweights_validate() {
assert_err!(
// Should get an invalid transaction error
result_no_stake,
TransactionValidityError::Invalid(InvalidTransaction::Call,)
TransactionValidityError::Invalid(InvalidTransaction::Custom(4))
);

// Increase the stake to be equal to the minimum
Expand Down Expand Up @@ -207,7 +207,7 @@ fn test_commit_weights_validate() {
assert_err!(
// Should get an invalid transaction error
result_no_stake,
TransactionValidityError::Invalid(InvalidTransaction::Call,)
TransactionValidityError::Invalid(InvalidTransaction::Custom(1))
);

// Increase the stake to be equal to the minimum
Expand Down Expand Up @@ -259,6 +259,66 @@ fn test_reveal_weights_dispatch_info_ok() {
});
}

#[test]
fn test_set_weights_validate() {
// Testing the signed extension validate function
// correctly filters the `set_weights` transaction.

new_test_ext(0).execute_with(|| {
let netuid: u16 = 1;
let coldkey = U256::from(0);
let hotkey: U256 = U256::from(1);
assert_ne!(hotkey, coldkey);

let who = hotkey; // The hotkey signs this transaction

let call = RuntimeCall::SubtensorModule(SubtensorCall::set_weights {
netuid,
dests: vec![1, 1],
weights: vec![1, 1],
version_key: 0,
});

// Create netuid
add_network(netuid, 0, 0);
// Register the hotkey
SubtensorModule::append_neuron(netuid, &hotkey, 0);
Owner::<Test>::insert(hotkey, coldkey);

let min_stake = 500_000_000_000;
// Set the minimum stake
SubtensorModule::set_weights_min_stake(min_stake);

// Verify stake is less than minimum
assert!(SubtensorModule::get_total_stake_for_hotkey(&hotkey) < min_stake);
let info: DispatchInfo =
DispatchInfoOf::<<Test as frame_system::Config>::RuntimeCall>::default();

let extension = pallet_subtensor::SubtensorSignedExtension::<Test>::new();
// Submit to the signed extension validate function
let result_no_stake = extension.validate(&who, &call.clone(), &info, 10);
// Should fail due to insufficient stake
assert_err!(
result_no_stake,
TransactionValidityError::Invalid(InvalidTransaction::Custom(3))
);

// Increase the stake to be equal to the minimum
SubtensorModule::increase_stake_on_hotkey_account(&hotkey, min_stake);

// Verify stake is equal to minimum
assert_eq!(
SubtensorModule::get_total_stake_for_hotkey(&hotkey),
min_stake
);

// Submit to the signed extension validate function
let result_min_stake = extension.validate(&who, &call.clone(), &info, 10);
// Now the call should pass
assert_ok!(result_min_stake);
});
}

#[test]
fn test_reveal_weights_validate() {
// Testing the signed extension validate function
Expand Down Expand Up @@ -306,7 +366,7 @@ fn test_reveal_weights_validate() {
assert_err!(
// Should get an invalid transaction error
result_no_stake,
TransactionValidityError::Invalid(InvalidTransaction::Call,)
TransactionValidityError::Invalid(InvalidTransaction::Custom(2))
);

// Increase the stake to be equal to the minimum
Expand Down
2 changes: 1 addition & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,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: 192,
spec_version: 193,
impl_version: 1,
apis: RUNTIME_API_VERSIONS,
transaction_version: 1,
Expand Down
Loading