Skip to content

Commit

Permalink
Merge branch 'dev' into fix/gosec-issues
Browse files Browse the repository at this point in the history
  • Loading branch information
gitferry committed Sep 2, 2024
2 parents 56d4a2b + 7fc65a9 commit f655d9b
Show file tree
Hide file tree
Showing 11 changed files with 123 additions and 81 deletions.
35 changes: 22 additions & 13 deletions cmd/sid/cli/btc_headers.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,19 @@ import (
"github.com/babylonlabs-io/staking-indexer/config"
"github.com/babylonlabs-io/staking-indexer/log"
"github.com/babylonlabs-io/staking-indexer/utils"

sdkmath "cosmossdk.io/math"
)

const (
outputFileFlag = "output"
withHeightFlag = "with-height"
defaultOutputFileName = "btc-headers.json"
filePermission = 0600
)

type HeadersState struct {
BtcHeaders []*bbnbtclightclienttypes.BTCHeaderInfo `json:"btc_headers,omitempty"`
}

var BtcHeaderCommand = cli.Command{
Name: "btc-headers",
Usage: "Output a range of BTC headers into a JSON file.",
Expand All @@ -43,6 +46,10 @@ var BtcHeaderCommand = cli.Command{
Usage: "The path to the output file",
Value: filepath.Join(config.DefaultHomeDir, defaultOutputFileName),
},
cli.BoolFlag{
Name: withHeightFlag,
Usage: "If it should fill the BTC block height property",
},
},
Action: btcHeaders,
}
Expand Down Expand Up @@ -92,18 +99,18 @@ func btcHeaders(ctx *cli.Context) error {
return fmt.Errorf("failed to initialize the BTC client: %w", err)
}

btcHeaders, err := BtcHeaderInfoList(btcClient, fromBlock, toBlock)
btcHeaders, err := BtcHeaderInfoList(btcClient, fromBlock, toBlock, ctx.Bool(withHeightFlag))
if err != nil {
return fmt.Errorf("failed to get BTC headers: %w", err)
}

genState := bbnbtclightclienttypes.GenesisState{
headersState := HeadersState{
BtcHeaders: btcHeaders,
}

bz, err := json.MarshalIndent(genState, "", " ")
bz, err := json.MarshalIndent(headersState, "", " ")
if err != nil {
return fmt.Errorf("failed to generate json to set to output file %+v: %w", genState, err)
return fmt.Errorf("failed to generate json to set to output file %+v: %w", headersState, err)
}

outputFilePath := ctx.String(outputFileFlag)
Expand All @@ -121,23 +128,25 @@ func btcHeaders(ctx *cli.Context) error {
}

// BtcHeaderInfoList queries the btc client for (fromBlk ~ toBlk) BTC blocks, converting to BTCHeaderInfo.
func BtcHeaderInfoList(btcClient btcscanner.Client, fromBlk, toBlk uint64) ([]*bbnbtclightclienttypes.BTCHeaderInfo, error) {
func BtcHeaderInfoList(btcClient btcscanner.Client, fromBlk, toBlk uint64, withHeight bool) ([]*bbnbtclightclienttypes.BTCHeaderInfo, error) {
btcHeaders := make([]*bbnbtclightclienttypes.BTCHeaderInfo, 0, toBlk-fromBlk+1)
var currenWork = sdkmath.ZeroUint()

for blkHeight := fromBlk; blkHeight <= toBlk; blkHeight++ {
blkHeader, err := btcClient.GetBlockHeaderByHeight(blkHeight)
if err != nil {
return nil, fmt.Errorf("failed to get block height %d from BTC client: %w", blkHeight, err)
}

headerWork := bbnbtclightclienttypes.CalcHeaderWork(blkHeader)
currenWork = bbnbtclightclienttypes.CumulativeWork(headerWork, currenWork)

headerBytes := babylontypes.NewBTCHeaderBytesFromBlockHeader(blkHeader)
info := &bbnbtclightclienttypes.BTCHeaderInfo{
Header: &headerBytes,
}

if withHeight {
info.Height = blkHeight
}

bbnBtcHeaderInfo := bbnbtclightclienttypes.NewBTCHeaderInfo(&headerBytes, headerBytes.Hash(), blkHeight, &currenWork)
btcHeaders = append(btcHeaders, bbnBtcHeaderInfo)
btcHeaders = append(btcHeaders, info)
}
return btcHeaders, nil
}
3 changes: 1 addition & 2 deletions cmd/sid/cli/btc_headers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func FuzzBtcHeaders(f *testing.F) {
Return(idxBlock.Header, nil).AnyTimes()
}

infos, err := cli.BtcHeaderInfoList(mockBtcClient, startHeight, endHeight)
infos, err := cli.BtcHeaderInfoList(mockBtcClient, startHeight, endHeight, true)
require.NoError(t, err)
require.EqualValues(t, len(infos), numBlocks)

Expand All @@ -45,7 +45,6 @@ func FuzzBtcHeaders(f *testing.F) {
headerBytes := babylontypes.NewBTCHeaderBytesFromBlockHeader(idxBlock.Header)
require.Equal(t, info.Header, &headerBytes)
require.EqualValues(t, info.Height, idxBlock.Height)
require.EqualValues(t, info.Hash, headerBytes.Hash())
}
})
}
13 changes: 7 additions & 6 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ var (

// Config is the main config for the fpd cli command
type Config struct {
LogLevel string `long:"loglevel" description:"Logging level for all subsystems" choice:"trace" choice:"debug" choice:"info" choice:"warn" choice:"error" choice:"fatal"`
BitcoinNetwork string `long:"bitcoinnetwork" description:"Bitcoin network to run on" choice:"mainnet" choice:"regtest" choice:"testnet" choice:"simnet" choice:"signet"`
BTCConfig *BTCConfig `group:"btcconfig" namespace:"btcconfig"`
DatabaseConfig *DBConfig `group:"dbconfig" namespace:"dbconfig"`
QueueConfig *QueueConfig `group:"queueconfig" namespace:"queueconfig"`
MetricsConfig *MetricsConfig `group:"metricsconfig" namespace:"metricsconfig"`
LogLevel string `long:"loglevel" description:"Logging level for all subsystems" choice:"trace" choice:"debug" choice:"info" choice:"warn" choice:"error" choice:"fatal"`
BitcoinNetwork string `long:"bitcoinnetwork" description:"Bitcoin network to run on" choice:"mainnet" choice:"regtest" choice:"testnet" choice:"simnet" choice:"signet"`
ExtraEventEnabled bool `long:"extraeventenabled" description:"Whether emitting non-default events is allowed"`
BTCConfig *BTCConfig `group:"btcconfig" namespace:"btcconfig"`
DatabaseConfig *DBConfig `group:"dbconfig" namespace:"dbconfig"`
QueueConfig *QueueConfig `group:"queueconfig" namespace:"queueconfig"`
MetricsConfig *MetricsConfig `group:"metricsconfig" namespace:"metricsconfig"`

BTCNetParams chaincfg.Params
}
Expand Down
1 change: 1 addition & 0 deletions consumer/event_consumer.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ type EventConsumer interface {
PushUnbondingEvent(ev *client.UnbondingStakingEvent) error
PushWithdrawEvent(ev *client.WithdrawStakingEvent) error
PushBtcInfoEvent(ev *client.BtcInfoEvent) error
PushConfirmedInfoEvent(ev *client.ConfirmedInfoEvent) error
Stop() error
}
12 changes: 12 additions & 0 deletions indexer/indexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,18 @@ func (si *StakingIndexer) HandleConfirmedBlock(b *types.IndexedBlock) error {
return fmt.Errorf("failed to save the last processed height: %w", err)
}

if si.cfg.ExtraEventEnabled {
// emit ConfirmedInfoEvent to send the confirmed height and tvl
confirmedTvl, err := si.is.GetConfirmedTvl()
if err != nil {
return fmt.Errorf("failed to get the confirmed tvl: %w", err)
}
confirmedInfoEvent := queuecli.NewConfirmedInfoEvent(uint64(b.Height), confirmedTvl)
if err := si.consumer.PushConfirmedInfoEvent(&confirmedInfoEvent); err != nil {
return fmt.Errorf("failed to push the confirmed info event: %w", err)
}
}

// record metrics
lastProcessedBtcHeight.Set(float64(b.Height))

Expand Down
24 changes: 7 additions & 17 deletions itest/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (

"github.com/babylonlabs-io/babylon/btcstaking"
bbndatagen "github.com/babylonlabs-io/babylon/testutil/datagen"
bbnbtclightclienttypes "github.com/babylonlabs-io/babylon/x/btclightclient/types"
queuecli "github.com/babylonlabs-io/staking-queue-client/client"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcutil"
Expand Down Expand Up @@ -99,11 +98,14 @@ func TestStakingLifeCycle(t *testing.T) {
stakingTxHash := stakingTx.TxHash()
tm.SendTxWithNConfirmations(t, stakingTx, int(k))

tm.CheckConfirmedInfoEvent(t, 100, 0)

// check that the staking tx is already stored
_ = tm.WaitForStakingTxStored(t, stakingTxHash)

// check the staking event is received by the queue
tm.CheckNextStakingEvent(t, stakingTxHash)
tm.CheckConfirmedInfoEvent(t, 102, uint64(testStakingData.StakingAmount))

// wait for the staking tx expires
if uint64(testStakingData.StakingTime) > k {
Expand Down Expand Up @@ -635,20 +637,15 @@ func TestTimeBasedCap(t *testing.T) {
func TestBtcHeaders(t *testing.T) {
r := rand.New(rand.NewSource(10))
blocksPerRetarget := 2016
genState := bbnbtclightclienttypes.DefaultGenesis()

initBlocksQnt := r.Intn(15) + blocksPerRetarget
btcd, btcClient := StartBtcClientAndBtcHandler(t, initBlocksQnt)

// from zero height
infos, err := cli.BtcHeaderInfoList(btcClient, 0, uint64(initBlocksQnt))
infos, err := cli.BtcHeaderInfoList(btcClient, 0, uint64(initBlocksQnt), true)
require.NoError(t, err)
require.Equal(t, len(infos), initBlocksQnt+1)

// should be valid on genesis, start from zero height.
genState.BtcHeaders = infos
require.NoError(t, genState.Validate())

generatedBlocksQnt := r.Intn(15) + 2
btcd.GenerateBlocks(generatedBlocksQnt)
totalBlks := initBlocksQnt + generatedBlocksQnt
Expand All @@ -657,22 +654,15 @@ func TestBtcHeaders(t *testing.T) {
fromBlockHeight := blocksPerRetarget - 1
toBlockHeight := totalBlks - 2

infos, err = cli.BtcHeaderInfoList(btcClient, uint64(fromBlockHeight), uint64(toBlockHeight))
infos, err = cli.BtcHeaderInfoList(btcClient, uint64(fromBlockHeight), uint64(toBlockHeight), true)
require.NoError(t, err)
require.Equal(t, len(infos), int(toBlockHeight-fromBlockHeight)+1)

// try to check if it is valid on genesis, should fail is not retarget block.
genState.BtcHeaders = infos
require.EqualError(t, genState.Validate(), "genesis block must be a difficulty adjustment block")
require.EqualValues(t, infos[len(infos)-1].Height, uint64(toBlockHeight))

// from retarget block
infos, err = cli.BtcHeaderInfoList(btcClient, uint64(blocksPerRetarget), uint64(totalBlks))
infos, err = cli.BtcHeaderInfoList(btcClient, uint64(blocksPerRetarget), uint64(totalBlks), true)
require.NoError(t, err)
require.Equal(t, len(infos), int(totalBlks-blocksPerRetarget)+1)

// check if it is valid on genesis
genState.BtcHeaders = infos
require.NoError(t, genState.Validate())
}

func getCovenantPrivKeys(t *testing.T) []*btcec.PrivateKey {
Expand Down
93 changes: 59 additions & 34 deletions itest/test_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,24 @@ import (
)

type TestManager struct {
Config *config.Config
Db kvdb.Backend
Si *indexer.StakingIndexer
BS *btcscanner.BtcPoller
WalletPrivKey *btcec.PrivateKey
serverStopper *signal.Interceptor
wg *sync.WaitGroup
BitcoindHandler *BitcoindTestHandler
WalletClient *rpcclient.Client
MinerAddr btcutil.Address
DirPath string
QueueConsumer *queuemngr.QueueManager
StakingEventChan <-chan queuecli.QueueMessage
UnbondingEventChan <-chan queuecli.QueueMessage
WithdrawEventChan <-chan queuecli.QueueMessage
BtcInfoEventChan <-chan queuecli.QueueMessage
VersionedParams *parser.ParsedGlobalParams
Config *config.Config
Db kvdb.Backend
Si *indexer.StakingIndexer
BS *btcscanner.BtcPoller
WalletPrivKey *btcec.PrivateKey
serverStopper *signal.Interceptor
wg *sync.WaitGroup
BitcoindHandler *BitcoindTestHandler
WalletClient *rpcclient.Client
MinerAddr btcutil.Address
DirPath string
QueueConsumer *queuemngr.QueueManager
StakingEventChan <-chan queuecli.QueueMessage
UnbondingEventChan <-chan queuecli.QueueMessage
WithdrawEventChan <-chan queuecli.QueueMessage
BtcInfoEventChan <-chan queuecli.QueueMessage
ConfirmedInfoEventChan <-chan queuecli.QueueMessage
VersionedParams *parser.ParsedGlobalParams
}

// bitcoin params used for testing
Expand Down Expand Up @@ -146,6 +147,8 @@ func StartWithBitcoinHandler(t *testing.T, h *BitcoindTestHandler, minerAddress
require.NoError(t, err)
unconfirmedEventChan, err := queueConsumer.BtcInfoQueue.ReceiveMessages()
require.NoError(t, err)
confirmedInfoEventChan, err := queueConsumer.ConfirmedInfoQueue.ReceiveMessages()
require.NoError(t, err)

db, err := cfg.DatabaseConfig.GetDbBackend()
require.NoError(t, err)
Expand Down Expand Up @@ -176,22 +179,23 @@ func StartWithBitcoinHandler(t *testing.T, h *BitcoindTestHandler, minerAddress
time.Sleep(3 * time.Second)

return &TestManager{
Config: cfg,
Si: si,
BS: scanner,
serverStopper: &interceptor,
wg: &wg,
BitcoindHandler: h,
WalletClient: rpcclient,
WalletPrivKey: walletPrivKey.PrivKey,
MinerAddr: minerAddress,
DirPath: dirPath,
QueueConsumer: queueConsumer,
StakingEventChan: stakingEventChan,
UnbondingEventChan: unbondingEventChan,
WithdrawEventChan: withdrawEventChan,
BtcInfoEventChan: unconfirmedEventChan,
VersionedParams: versionedParams,
Config: cfg,
Si: si,
BS: scanner,
serverStopper: &interceptor,
wg: &wg,
BitcoindHandler: h,
WalletClient: rpcclient,
WalletPrivKey: walletPrivKey.PrivKey,
MinerAddr: minerAddress,
DirPath: dirPath,
QueueConsumer: queueConsumer,
StakingEventChan: stakingEventChan,
UnbondingEventChan: unbondingEventChan,
WithdrawEventChan: withdrawEventChan,
BtcInfoEventChan: unconfirmedEventChan,
ConfirmedInfoEventChan: confirmedInfoEventChan,
VersionedParams: versionedParams,
}
}

Expand All @@ -214,7 +218,10 @@ func ReStartFromHeight(t *testing.T, tm *TestManager, height uint64) *TestManage
func DefaultStakingIndexerConfig(homePath string) *config.Config {
defaultConfig := config.DefaultConfigWithHome(homePath)

// both wallet and node are bicoind
// enable emitting extra events for testing
defaultConfig.ExtraEventEnabled = true

// both wallet and node are bitcoind
defaultConfig.BTCNetParams = *regtestParams

bitcoindHost := "127.0.0.1:18443"
Expand Down Expand Up @@ -361,6 +368,23 @@ func (tm *TestManager) CheckNextWithdrawEvent(t *testing.T, stakingTxHash chainh
require.NoError(t, err)
}

func (tm *TestManager) CheckConfirmedInfoEvent(t *testing.T, height, tvl uint64) {
var confirmedInfoEv queuecli.ConfirmedInfoEvent

for {
confirmedInfoEventBytes := <-tm.ConfirmedInfoEventChan
err := tm.QueueConsumer.ConfirmedInfoQueue.DeleteMessage(confirmedInfoEventBytes.Receipt)
require.NoError(t, err)
err = json.Unmarshal([]byte(confirmedInfoEventBytes.Body), &confirmedInfoEv)
require.NoError(t, err)
if height != confirmedInfoEv.Height {
continue
}
require.Equal(t, confirmedInfoEv.Tvl, tvl)
return
}
}

func (tm *TestManager) CheckNextUnconfirmedEvent(t *testing.T, confirmedTvl, totalTvl uint64) {
var btcInfoEvent queuecli.BtcInfoEvent

Expand All @@ -376,6 +400,7 @@ func (tm *TestManager) CheckNextUnconfirmedEvent(t *testing.T, confirmedTvl, tot
if totalTvl != btcInfoEvent.UnconfirmedTvl {
continue
}

return
}
}
Expand Down
14 changes: 14 additions & 0 deletions testutils/mocks/event_consumer.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 0 additions & 5 deletions tools/go.mod

This file was deleted.

Empty file removed tools/go.sum
Empty file.
4 changes: 0 additions & 4 deletions tools/tools.go

This file was deleted.

0 comments on commit f655d9b

Please sign in to comment.