math

package
v0.0.0-beta.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 30, 2023 License: Apache-2.0 Imports: 9 Imported by: 0

README

Aggregating Oracle Prices On-Chain

Overview

Definitions

  • Price: The price of an asset at a given time.
  • Delta: The difference between the current price and the previous price. This can be positive or negative.
  • Aggregation Strategy: The method by which the deltas are aggregated across multiple oracle sources.

Note: The price aggregation strategy might vary based on the currency pair strategy utilized by the vote extension handler. For example, if the vote extension is implemented to submit a delta, the aggregation strategy must aggregate deltas. If the vote extension is implemented to submit a price, the aggregation strategy must aggregate prices. By default, the vote extension handler will submit deltas which are converted to real prices before being aggregated. This is the recommended approach.

This module provides the default implementation for a price aggregation strategy across multiple oracle sources on-chain. It is designed to be used as the aggregation function for the PreBlock handler. This implementation can be used as a reference for other implementations. For a reference as to how these strategies can be implemented, please reference the aggregator module.

Implementation

The PreBlock handler is implemented in preblock.go. This handler is registered with the application in app.go. The handler is called by the ABCI application before the block is committed to the chain - in PreBlock during FinalizeBlock.

This implementation will first associate the relative voting power of each validator given the price update that they have submitted through their vote extensions. After the voting power is calculated, the price information is aggregated across all validators by first sorting the prices in ascending order and then taking the stake weighted median of the prices.

For example, if there are 3 validators with the following prices:

Validator 1: 100
Validator 2: 200
Validator 3: 300

Assume the validators have the following voting power:

Validator 1: 10
Validator 2: 20
Validator 3: 20

The final aggregated price will be 200 which is the median of the sorted prices.

Another example, if there are 3 validators with the following prices:

Validator 1: 100
Validator 2: 200
Validator 3: 300

Assume the validators have the following voting power:

Validator 1: 10
Validator 2: 20
Validator 3: 30

The final aggregated price will be 250 which is the median of the sorted prices. Notice, that the price aggregation strategy selects the price update where the voting power is greater than or equal to 50%. In this case, the price update from Validator 2 is selected.

As a final example, if there are 3 validators with the following prices:

Validator 1: 100
Validator 2: 200
Validator 3: 300

Assume the validators have the following voting power:

Validator 1: 10
Validator 2: 10
Validator 3: 100

The final aggregated price will be 300 which is the median of the sorted prices.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var DefaultPowerThreshold = math.LegacyNewDecWithPrec(667, 3)

DefaultPowerThreshold defines the total voting power % that must be submitted in order for a currency pair to be considered for the final oracle price. We provide a default supermajority threshold of 2/3+.

Functions

func ComputeVoteWeightedMedian

func ComputeVoteWeightedMedian(priceInfo VoteWeightedPriceInfo) *big.Int

ComputeVoteWeightedMedian computes the stake-weighted median price for a given asset.

func VoteWeightedMedian

func VoteWeightedMedian(
	ctx sdk.Context,
	logger log.Logger,
	validatorStore ValidatorStore,
	threshold math.LegacyDec,
) aggregator.AggregateFn

VoteWeightedMedian returns an aggregation function that computes the stake weighted median price as the final deterministic oracle price for any qualifying currency pair (base, quote). There are a few things to note about the implementation:

  1. Price updates for a given currency pair will only be written to state if the power % threshold is met. The threshold is determined by the total voting power of all validators that submitted a price update for a given currency pair divided by the total network voting power. The threshold to meet is configurable by developers.
  2. In the case where there are not enough price updates for a given currency pair, the price will not be included in the final set of oracle prices.
  3. Given the threshold is met, the final oracle price for a given currency pair is the median price weighted by the stake of each validator that submitted a price.

func VoteWeightedMedianFromContext

func VoteWeightedMedianFromContext(
	logger log.Logger,
	validatorStore ValidatorStore,
	threshold math.LegacyDec,
) aggregator.AggregateFnFromContext

VoteWeightedMedianFromContext returns a new VoteWeightedMedian aggregate function that is parametrized by the latest state of the application.

Types

type ValidatorStore

type ValidatorStore interface {
	ValidatorByConsAddr(ctx context.Context, addr sdk.ConsAddress) (stakingtypes.ValidatorI, error)
	TotalBondedTokens(ctx context.Context) (math.Int, error)
}

ValidatorStore defines the interface contract required for calculating stake-weighted median prices + total voting power for a given currency pair.

type VoteWeightedPriceInfo

type VoteWeightedPriceInfo struct {
	Prices      []VoteWeightedPricePerValidator
	TotalWeight math.Int
}

VoteWeightPriceInfo tracks the stake weight(s) + price(s) for a given currency pair.

type VoteWeightedPricePerValidator

type VoteWeightedPricePerValidator struct {
	VoteWeight math.Int
	Price      *big.Int
}

VoteWeightPrice defines a price update that includes the stake weight of the validator.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL