@@ -8,10 +8,14 @@ import (
88 "cosmossdk.io/log"
99 "cosmossdk.io/math"
1010
11+ "github.com/btcsuite/btcd/chaincfg/chainhash"
12+ "github.com/btcsuite/btcd/rpcclient"
13+
1114 abci "github.com/cometbft/cometbft/abci/types"
1215 cmtproto "github.com/cometbft/cometbft/proto/tendermint/types"
1316 "github.com/cosmos/cosmos-sdk/baseapp"
1417 sdk "github.com/cosmos/cosmos-sdk/types"
18+ "github.com/sideprotocol/side/x/oracle/keeper"
1519 "github.com/sideprotocol/side/x/oracle/types"
1620)
1721
@@ -20,18 +24,34 @@ type ProceOracleVoteExtHandler struct {
2024 logger log.Logger
2125 currentBlock int64 // current block height
2226 lastPriceSyncTS int64 // last time we synced prices
27+ bitcoinClient * rpcclient.Client
2328 // providerTimeout time.Duration // timeout for fetching prices from providers
2429 // providers map[string]Provider // mapping of provider name to provider (e.g. Binance -> BinanceProvider)
2530 // providerPairs map[string][]keeper.CurrencyPair // mapping of provider name to supported pairs (e.g. Binance -> [ATOM/USD])
2631
27- // Keeper keeper.Keeper // keeper of our oracle module
32+ Keeper keeper.Keeper // keeper of our oracle module
33+ config * types.OracleConfig
2834}
2935
30- func NewPriceOracleVoteExtHandler (logger log.Logger , valStore baseapp.ValidatorStore ) ProceOracleVoteExtHandler {
36+ func NewPriceOracleVoteExtHandler (logger log.Logger , valStore baseapp.ValidatorStore , oracleKeeper keeper.Keeper , config * types.OracleConfig ) ProceOracleVoteExtHandler {
37+ client , err := rpcclient .New (& rpcclient.ConnConfig {
38+ Host : config .BitcoinRpc ,
39+ User : config .BitcoinRpcUser ,
40+ Pass : config .BitcoinRpcPass ,
41+ HTTPPostMode : config .HTTPPostMode ,
42+ DisableTLS : config .DisableTLS ,
43+ }, nil )
44+ if err != nil {
45+ panic ("unable to create bitcoin rpc" )
46+ }
47+
3148 return ProceOracleVoteExtHandler {
32- logger : logger ,
33- currentBlock : 0 ,
34- valStore : valStore ,
49+ logger : logger ,
50+ currentBlock : 0 ,
51+ valStore : valStore ,
52+ Keeper : oracleKeeper ,
53+ bitcoinClient : client ,
54+ config : config ,
3555 }
3656}
3757
@@ -43,10 +63,36 @@ func (h *ProceOracleVoteExtHandler) ExtendVoteHandler() sdk.ExtendVoteHandler {
4363 prices := h .getAllVolumeWeightedPrices ()
4464 h .lastPriceSyncTS = req .Time .UnixMilli ()
4565
66+ tips , err := h .bitcoinClient .GetChainTips ()
67+ if err != nil {
68+ return nil , fmt .Errorf ("failed to fetch best block header: %w" , err )
69+ }
70+
71+ hash , err := chainhash .NewHashFromStr (tips [0 ].Hash )
72+ height := tips [0 ].Height
73+ if err != nil {
74+ return nil , fmt .Errorf ("failed to fetch best block header: %w" , err )
75+ }
76+ b , err := h .bitcoinClient .GetBlockHeader (hash )
77+ if err != nil {
78+ return nil , fmt .Errorf ("failed to fetch header: %w" , err )
79+ }
80+
81+ header := types.BlockHeader {
82+ Version : uint64 (b .Version ),
83+ Hash : b .BlockHash ().String (),
84+ Height : uint64 (height ),
85+ PreviousBlockHash : b .PrevBlock .String (),
86+ MerkleRoot : b .MerkleRoot .String (),
87+ Nonce : uint64 (b .Nonce ),
88+ Bits : fmt .Sprintf ("%x" , b .Bits ),
89+ Time : uint64 (b .Timestamp .Unix ()),
90+ }
91+
4692 voteExt := types.OracleVoteExtension {
4793 Height : req .Height ,
4894 Prices : prices ,
49- Blocks : []* types.BlockHeader {},
95+ Blocks : []* types.BlockHeader {& header },
5096 }
5197
5298 // bz := []byte{}
@@ -223,22 +269,25 @@ func (h *ProceOracleVoteExtHandler) PreBlocker(ctx sdk.Context, req *abci.Reques
223269 return nil , err
224270 }
225271
226- prices , err := h .computeStakeWeightedOraclePrices (ctx , injectedVoteExtTx )
272+ prices , headers , err := h .extractPricesAndBlockHeaders (ctx , injectedVoteExtTx )
227273 if err != nil {
228274 return nil , err
229275 }
230276
231- // set oracle prices using the passed in context, which will make these prices available in the current block
232- // if err := h.keeper.SetOraclePrices(ctx, injectedVoteExtTx.StakeWeightedPrices); err != nil {
233- // return nil, err
234- // }
277+ for symbol , price := range prices {
278+ h .Keeper .SetPrice (ctx , symbol , price .String ())
279+ }
280+
281+ for _ , head := range headers {
282+ h .Keeper .SetBlockHeader (ctx , head )
283+ }
235284
236285 h .logger .Warn ("Oracle Final States" , "price" , prices )
237286
238287 return res , nil
239288}
240289
241- func (h * ProceOracleVoteExtHandler ) computeStakeWeightedOraclePrices (ctx sdk.Context , commit abci.ExtendedCommitInfo ) (map [string ]math.LegacyDec , error ) {
290+ func (h * ProceOracleVoteExtHandler ) extractPricesAndBlockHeaders (ctx sdk.Context , commit abci.ExtendedCommitInfo ) (map [string ]math.LegacyDec , [] * types. BlockHeader , error ) {
242291 // requiredPairs := h.keeper.GetSupportedPairs(ctx)
243292 // requiredPairs := []string{"BTCUSD"}
244293 stakeWeightedPrices := make (map [string ]math.LegacyDec , len (types .PRICE_CACHE )) // base -> average stake-weighted price
@@ -247,6 +296,7 @@ func (h *ProceOracleVoteExtHandler) computeStakeWeightedOraclePrices(ctx sdk.Con
247296 // }
248297
249298 var totalStake int64
299+ var blockHeaders []* types.BlockHeader
250300 for _ , v := range commit .Votes {
251301 if v .BlockIdFlag != cmtproto .BlockIDFlagCommit {
252302 continue
@@ -256,7 +306,17 @@ func (h *ProceOracleVoteExtHandler) computeStakeWeightedOraclePrices(ctx sdk.Con
256306 // if err := json.Unmarshal(v.VoteExtension, &voteExt); err != nil {
257307 if err := voteExt .Unmarshal (v .VoteExtension ); err != nil {
258308 h .logger .Error ("failed to decode vote extension" , "err" , err , "validator" , fmt .Sprintf ("%x" , v .Validator .Address ))
259- return nil , err
309+ return nil , nil , err
310+ }
311+
312+ h .logger .Warn ("extension" , "validator" , hex .EncodeToString (v .Validator .Address ), "extension" , voteExt )
313+
314+ if blockHeaders == nil {
315+ blockHeaders = voteExt .Blocks
316+ } else {
317+ if len (blockHeaders ) != len (voteExt .Blocks ) {
318+ h .logger .Error ("inconsistent state" , "left" , blockHeaders , "right" , voteExt .Blocks )
319+ }
260320 }
261321
262322 totalStake += v .Validator .Power
@@ -283,15 +343,15 @@ func (h *ProceOracleVoteExtHandler) computeStakeWeightedOraclePrices(ctx sdk.Con
283343 }
284344
285345 if totalStake == 0 {
286- return nil , nil
346+ return nil , nil , nil
287347 }
288348
289349 // finalize average by dividing by total stake, i.e. total weights
290350 for base , price := range stakeWeightedPrices {
291351 stakeWeightedPrices [base ] = price .QuoInt64 (totalStake )
292352 }
293353
294- return stakeWeightedPrices , nil
354+ return stakeWeightedPrices , blockHeaders , nil
295355}
296356
297357// func compareOraclePrices(p1, p2 map[string]math.LegacyDec) error {
0 commit comments