Skip to content

Commit ca2ef40

Browse files
author
lazyluis
committed
add bitcoin headers and enable config
1 parent 558f686 commit ca2ef40

File tree

12 files changed

+233
-27
lines changed

12 files changed

+233
-27
lines changed

app/app.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ import (
139139
lendingtypes "github.com/sideprotocol/side/x/lending/types"
140140
oracleabci "github.com/sideprotocol/side/x/oracle/abci"
141141

142+
oraclekeeper "github.com/sideprotocol/side/x/oracle/keeper"
142143
oracletypes "github.com/sideprotocol/side/x/oracle/types"
143144

144145
// this line is used by starport scaffolding # stargate/app/moduleImport
@@ -290,6 +291,7 @@ type App struct {
290291
AuctionKeeper auctionkeeper.Keeper
291292
DLCKeeper dlckeeper.Keeper
292293
LendingKeeper lendingkeeper.Keeper
294+
OracleKeeper oraclekeeper.Keeper
293295
// this line is used by starport scaffolding # stargate/app/keeperDeclaration
294296

295297
// the module manager
@@ -360,7 +362,7 @@ func New(
360362
capabilitytypes.StoreKey, group.StoreKey, icacontrollertypes.StoreKey, consensusparamtypes.StoreKey,
361363
ibcfeetypes.StoreKey, wasmtypes.StoreKey,
362364
btcbridgetypes.StoreKey, auctiontypes.StoreKey,
363-
dlctypes.StoreKey, lendingtypes.StoreKey,
365+
dlctypes.StoreKey, lendingtypes.StoreKey, oracletypes.StoreKey, oracletypes.MemStoreKey,
364366
// this line is used by starport scaffolding # stargate/app/storeKey
365367
)
366368

@@ -668,6 +670,8 @@ func New(
668670
)
669671
lendingModule := lendingmodule.NewAppModule(appCodec, app.LendingKeeper)
670672

673+
app.OracleKeeper = oraclekeeper.NewKeeper(appCodec, keys[oracletypes.StoreKey], keys[oracletypes.MemStoreKey], "")
674+
671675
wasmDir := filepath.Join(homePath, "wasm")
672676
wasmConfig, err := wasm.ReadWasmConfig(appOpts)
673677
if err != nil {
@@ -960,7 +964,7 @@ func New(
960964
app.SetBeginBlocker(app.BeginBlocker)
961965
app.SetEndBlocker(app.EndBlocker)
962966

963-
voteExtHander := oracleabci.NewPriceOracleVoteExtHandler(app.Logger(), app.StakingKeeper)
967+
voteExtHander := oracleabci.NewPriceOracleVoteExtHandler(app.Logger(), app.StakingKeeper, app.OracleKeeper, &oracleConfig)
964968
// propHandler := oracle.NewProposalHandler(app.Logger(), app.StakingKeeper)
965969

966970
app.SetExtendVoteHandler(voteExtHander.ExtendVoteHandler())

cmd/sided/cmd/commands.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626
genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli"
2727

2828
"github.com/sideprotocol/side/app"
29-
oracleabci "github.com/sideprotocol/side/x/oracle/abci"
29+
oracle "github.com/sideprotocol/side/x/oracle/module"
3030
)
3131

3232
func initRootCmd(
@@ -45,8 +45,8 @@ func initRootCmd(
4545

4646
// server.AddCommands(rootCmd, app.DefaultNodeHome, newApp, appExport, addModuleInitFlags)
4747
opts := server.StartCmdOptions{
48-
PostSetup: oracleabci.Start,
49-
PostSetupStandalone: oracleabci.Start,
48+
PostSetup: oracle.Start,
49+
PostSetupStandalone: oracle.Start,
5050
}
5151
server.AddCommandsWithStartCmdOptions(rootCmd, app.DefaultNodeHome, newApp, appExport, opts)
5252

cmd/sided/cmd/config.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,17 @@ func initAppConfig() (string, interface{}) {
6060
// # This is the number of wasm vm instances we keep cached in memory for speed-up
6161
// # Warning: this is currently unstable and may lead to crashes, best to keep for 0 unless testing locally
6262
// lru_size = 0`
63-
6463
customAppTemplate := serverconfig.DefaultConfigTemplate + `
6564
[oracle]
6665
# Validator node should set this to true
6766
enable = false
67+
68+
bitcoin_rpc = "192.248.150.102:18332"
69+
bitcoin_rpc_user = "side"
70+
bitcoin_rpc_password = "12345678"
71+
http_post_mode = true
72+
disable_tls = true
73+
6874
`
6975

7076
return customAppTemplate, customAppConfig

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ require (
8383
github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect
8484
github.com/bits-and-blooms/bitset v1.8.0 // indirect
8585
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect
86+
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect
87+
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect
8688
github.com/bufbuild/protocompile v0.14.0 // indirect
8789
github.com/bufbuild/protoplugin v0.0.0-20240323223605-e2735f6c31ee // indirect
8890
github.com/bufbuild/protovalidate-go v0.6.2 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,11 +319,13 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtyd
319319
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo=
320320
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
321321
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
322+
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw=
322323
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
323324
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
324325
github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I=
325326
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
326327
github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
328+
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc=
327329
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
328330
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
329331
github.com/bufbuild/buf v1.34.0 h1:rZSVfYS5SakOe6ds9PDjbHVwOc+vBGVWNW9Ei+Rg/+c=

x/oracle/abci/extenstion.go

Lines changed: 75 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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 {

x/oracle/keeper/bitcoin.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package keeper
2+
3+
import (
4+
sdk "github.com/cosmos/cosmos-sdk/types"
5+
6+
"github.com/sideprotocol/side/x/oracle/types"
7+
)
8+
9+
func (k Keeper) HasBlockHeader(ctx sdk.Context, hash string) bool {
10+
store := ctx.KVStore(k.storeKey)
11+
return store.Has(types.BitcoinHeaderKey(hash))
12+
}
13+
14+
func (k Keeper) SetBlockHeader(ctx sdk.Context, header *types.BlockHeader) {
15+
store := ctx.KVStore(k.storeKey)
16+
17+
bz := k.cdc.MustMarshal(header)
18+
store.Set(types.BitcoinHeaderKey(header.Hash), bz)
19+
}
20+
21+
func (k Keeper) GetBlockHeader(ctx sdk.Context, hash string) types.BlockHeader {
22+
store := ctx.KVStore(k.storeKey)
23+
var header types.BlockHeader
24+
bz := store.Get(types.BitcoinHeaderKey(hash))
25+
k.cdc.MustUnmarshal(bz, &header)
26+
return header
27+
}

x/oracle/keeper/keeper.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package keeper
22

33
import (
4+
"cosmossdk.io/log"
5+
46
"github.com/cosmos/cosmos-sdk/codec"
7+
sdk "github.com/cosmos/cosmos-sdk/types"
8+
"github.com/sideprotocol/side/x/oracle/types"
59

610
storetypes "cosmossdk.io/store/types"
711
)
@@ -27,3 +31,22 @@ func NewKeeper(
2731
authority: authority,
2832
}
2933
}
34+
35+
func (k Keeper) Logger(ctx sdk.Context) log.Logger {
36+
sdkCtx := sdk.UnwrapSDKContext(ctx)
37+
return sdkCtx.Logger().With("module", "x/"+types.ModuleName)
38+
}
39+
40+
func (k Keeper) SetParams(ctx sdk.Context, params types.Params) {
41+
store := ctx.KVStore(k.storeKey)
42+
bz := k.cdc.MustMarshal(&params)
43+
store.Set(types.ParamsStoreKey, bz)
44+
}
45+
46+
func (k Keeper) GetParams(ctx sdk.Context) types.Params {
47+
store := ctx.KVStore(k.storeKey)
48+
var params types.Params
49+
bz := store.Get(types.ParamsStoreKey)
50+
k.cdc.MustUnmarshal(bz, &params)
51+
return params
52+
}

x/oracle/keeper/price.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package keeper
2+
3+
import (
4+
"fmt"
5+
6+
sdkmath "cosmossdk.io/math"
7+
sdk "github.com/cosmos/cosmos-sdk/types"
8+
9+
"github.com/sideprotocol/side/x/oracle/types"
10+
)
11+
12+
func (k Keeper) HasPrice(ctx sdk.Context, symbol string) bool {
13+
store := ctx.KVStore(k.storeKey)
14+
return store.Has(types.PriceKey(symbol))
15+
}
16+
17+
func (k Keeper) SetPrice(ctx sdk.Context, symbol, price string) {
18+
store := ctx.KVStore(k.storeKey)
19+
20+
store.Set(types.PriceKey(symbol), []byte(price))
21+
}
22+
23+
func (k Keeper) GetPrice(ctx sdk.Context, symbol string) (sdkmath.LegacyDec, error) {
24+
store := ctx.KVStore(k.storeKey)
25+
26+
bz := store.Get(types.PriceKey(symbol))
27+
if bz == nil {
28+
return sdkmath.LegacyZeroDec(), fmt.Errorf("no price set")
29+
}
30+
31+
price, _ := sdkmath.LegacyNewDecFromStr(string(bz))
32+
return price, nil
33+
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package abci
1+
package oracle
22

33
import (
44
"context"
@@ -16,7 +16,7 @@ type Starter struct {
1616
// Subscrible Prices from providers
1717
func Start(svrCtx *server.Context, clientCtx client.Context, ctx context.Context, g *errgroup.Group) error {
1818

19-
svrCtx.Logger.Info("service start", "module", "oracle", "msg", "Start Oracle Price Subscriber")
19+
svrCtx.Logger.Info("price service", "module", "oracle", "msg", "Start Oracle Price Subscriber")
2020

2121
// g.Go(func() error { return binance.Subscribe(svrCtx, ctx) })
2222
// g.Go(func() error { return okex.Subscribe(svrCtx) })

0 commit comments

Comments
 (0)