Incentives

Each subnet must have an incentive mechanism for each node to be incentivized based on the percentage of ownership of the rewards generated for the subnet. This allows subnets the freedom to have any architecture with no bounds.

P2P Technology in Hypertensor Subnets

Why P2P is Necessary for Subnets

Hypertensor employs a validation and attestation consensus model for subnet validation. This model requires 66% attestation from participating subnet nodes to successfully distribute incentives. Due to this design, Hypertensor subnets are susceptible to similar attack vectors as other Proof-of-Stake (PoS) blockchains, making a non-P2P architecture unsuitable for secure and decentralized node onboarding.

Using P2P for Secure Onboarding and Data Distribution

To maintain network integrity, it is strongly recommended that each subnet adopt a P2P architecture using libp2p or similar libraries. This allows:

  • Secure entry through Proof-of-Stake (PoS) requirements, preventing Sybil attacks.

  • Efficient routing via peer routing tables ensures that all nodes can discover and communicate with each other.

  • Scalable data distribution through DHT storage methods, allowing consensus-critical data to be consistently available.

Ensuring Data Consistency and Validator Accuracy

On each epoch, a subnet node is selected to submit incentives data, which all nodes must verify. To ensure a 100% accuracy requirement, all participating nodes must have identical access to the same data. This can be achieved by using:

  • Distributed Hash Tables (DHTs) Storage to store and share subnet data efficiently.

  • Ledger-based storage methods to ensure data consistency across all nodes.

  • Gossip-based subscriptions for real-time data propagation.

These mechanisms ensure that when a validator submits data, other nodes can independently verify it without discrepancies, just like blockchains.

By leveraging P2P networking, Hypertensor subnets can achieve robust decentralization, efficient consensus, and secure incentive distribution, making them resilient to attacks and ensuring trustless validation.

Rewards

Each subnet has a set amount of rewards based on the delegate stake balance of the subnet itself.

Examples:

The DSN standard currently uses an incentive mechanism based on the percentage of transformer blocks they host.

Adding inference TPS as a weight of the incentives equation is planned for the DSN standard. As a subnet developer, one could build any incentive mechanism for the subnet's use case(s).

The incentives can be based on anything:

  • Speed (using a ledger, IPFS, in-subnet ledger, Hypertensor smart contracts, etc.)

  • Accuracy (using a ledger, IPFS, in-subnet ledger, Hypertensor smart contracts, etc.)

  • Roles

  • Accounting (Hypertensor accounting mechanism)

  • Ledger validation

  • Attestation accuracy (Hypertensor validator mechanism)

  • etc.

Each incentive mechanism variable should be able to be verified. For example, in the subnet-llm-template, each subnet node can verify that another subnet node is hosting the blocks the system says they are by running its POI (Proof of Inference) mechanism.


Validator

At the start of each epoch, a blockchain validator will choose a subnet validator (for each subnet) at random. This subnet validator must submit each subnet node's incentive weight.

The subnet must always be listening for this to know which subnet node is responsible for submitting the data on that epoch.

The chosen subnet validator will be rewarded based on the accuracy of the data calculated from the attestation rate.

Submission

Each subnet must submit validation data to the blockchain per epoch of the weight of each subnet node.

Attestation

For the submitted data to qualify for rewards in a given epoch, it must achieve an attestation rate of at least 66% from all subnet nodes.


Validator Submission:

keypair = Keypair.create_from_uri('//Alice') # replace with your mnemonic phrase

call = substrate.compose_call(
  call_module='Network',
  call_function='validate',
  call_params={
    'subnet_id': subnet_id,
    'data': data,
    'args': args,
  }
)

extrinsic = substrate.create_signed_extrinsic(call=call, keypair=keypair)

receipt = substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True)

Arguments:

  • subnet_id: The subnet ID of the subnet

    • This should be initialized into the class responsible for consensus.

  • data: The data in the following format as a Vector:

    • pub struct SubnetNodeData {
          pub peer_id: PeerId,
          pub score: u128,
      }
    • In Python:

      • data = [{
            'peer_id': str,
            'score': int,
        }]

  • args: Arbitrary arguments the subnet can utilize during consensus.

Each validator submission is stored as aSubnetRewardsSubmissionunder the subnet ID and epoch:

pub type SubnetRewardsSubmission<T: Config> = StorageDoubleMap<
    _,
    Blake2_128Concat,
    u32, // subnet ID
    Identity,
    u32, // epoch
    RewardsData<T::AccountId>,
>;
pub struct RewardsData<AccountId> {
    pub validator: AccountId,
    pub attests: Attests<AccountId>,
    pub data: Vec<SubnetNodeData>,
    pub args: Option<BoundedVec<u8, DefaultValidatorArgsLimit>>,
}

Data Attestation:

keypair = Keypair.create_from_uri('//Alice') # replace with your mnemonic phrase

call = substrate.compose_call(
  call_module='Network',
  call_function='attest',
  call_params={
    'subnet_id': subnet_id,
  }
)

extrinsic = substrate.create_signed_extrinsic(call=call, keypair=keypair)

receipt = substrate.submit_extrinsic(extrinsic, wait_for_inclusion=True)

Arguments:

  • subnet_id: The subnet ID of the subnet

    • This should be initialized into the class responsible for consensus.

Each subnet node attestation updates theSubnetRewardsSubmissionto to include the attestor account_id and block attested. The data can be used in the following epoch(s) to be used for more accurate rewards, such as speed of attestation.

Last updated