Skip to content

Commit

Permalink
chore: Replace fast sync with batch processing (#132)
Browse files Browse the repository at this point in the history
Closes #118. Notable changes:
* remove fast sync completely
* introduce batch process for catching up
* introduce signature submission interval to config
* introduce batch submission size to config
  • Loading branch information
gitferry committed Nov 25, 2024
1 parent dbc246f commit aaef57e
Show file tree
Hide file tree
Showing 8 changed files with 266 additions and 546 deletions.
121 changes: 120 additions & 1 deletion clientcontroller/babylon/babylon.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/btcsuite/btcd/btcec/v2/schnorr"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg"
cmtcrypto "github.com/cometbft/cometbft/proto/tendermint/crypto"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkquery "github.com/cosmos/cosmos-sdk/types/query"
sttypes "github.com/cosmos/cosmos-sdk/x/staking/types"
Expand Down Expand Up @@ -145,7 +146,125 @@ func (bc *BabylonController) RegisterFinalityProvider(
return &types.TxResponse{TxHash: res.TxHash}, nil
}

func (bc *BabylonController) QueryFinalityProviderSlashedOrJailed(fpPk *btcec.PublicKey) (slashed bool, jailed bool, err error) {
// CommitPubRandList commits a list of Schnorr public randomness via a MsgCommitPubRand to Babylon
// it returns tx hash and error
func (bc *BabylonController) CommitPubRandList(
fpPk *btcec.PublicKey,
startHeight uint64,
numPubRand uint64,
commitment []byte,
sig *schnorr.Signature,
) (*types.TxResponse, error) {
msg := &finalitytypes.MsgCommitPubRandList{
Signer: bc.MustGetTxSigner(),
FpBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(fpPk),
StartHeight: startHeight,
NumPubRand: numPubRand,
Commitment: commitment,
Sig: bbntypes.NewBIP340SignatureFromBTCSig(sig),
}

unrecoverableErrs := []*sdkErr.Error{
finalitytypes.ErrInvalidPubRand,
finalitytypes.ErrTooFewPubRand,
finalitytypes.ErrNoPubRandYet,
btcstakingtypes.ErrFpNotFound,
}

res, err := bc.reliablySendMsg(msg, emptyErrs, unrecoverableErrs)
if err != nil {
return nil, err
}

return &types.TxResponse{TxHash: res.TxHash}, nil
}

// SubmitFinalitySig submits the finality signature via a MsgAddVote to Babylon
func (bc *BabylonController) SubmitFinalitySig(
fpPk *btcec.PublicKey,
block *types.BlockInfo,
pubRand *btcec.FieldVal,
proof []byte, // TODO: have a type for proof
sig *btcec.ModNScalar,
) (*types.TxResponse, error) {
return bc.SubmitBatchFinalitySigs(
fpPk, []*types.BlockInfo{block}, []*btcec.FieldVal{pubRand},
[][]byte{proof}, []*btcec.ModNScalar{sig},
)
}

// SubmitBatchFinalitySigs submits a batch of finality signatures to Babylon
func (bc *BabylonController) SubmitBatchFinalitySigs(
fpPk *btcec.PublicKey,
blocks []*types.BlockInfo,
pubRandList []*btcec.FieldVal,
proofList [][]byte,
sigs []*btcec.ModNScalar,
) (*types.TxResponse, error) {
if len(blocks) != len(sigs) {
return nil, fmt.Errorf("the number of blocks %v should match the number of finality signatures %v", len(blocks), len(sigs))
}

msgs := make([]sdk.Msg, 0, len(blocks))
for i, b := range blocks {
cmtProof := cmtcrypto.Proof{}
if err := cmtProof.Unmarshal(proofList[i]); err != nil {
return nil, err
}

msg := &finalitytypes.MsgAddFinalitySig{
Signer: bc.MustGetTxSigner(),
FpBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(fpPk),
BlockHeight: b.Height,
PubRand: bbntypes.NewSchnorrPubRandFromFieldVal(pubRandList[i]),
Proof: &cmtProof,
BlockAppHash: b.Hash,
FinalitySig: bbntypes.NewSchnorrEOTSSigFromModNScalar(sigs[i]),
}
msgs = append(msgs, msg)
}

unrecoverableErrs := []*sdkErr.Error{
finalitytypes.ErrInvalidFinalitySig,
finalitytypes.ErrPubRandNotFound,
btcstakingtypes.ErrFpAlreadySlashed,
}

res, err := bc.reliablySendMsgs(msgs, emptyErrs, unrecoverableErrs)
if err != nil {
return nil, err
}

if res == nil {
return &types.TxResponse{}, nil
}

return &types.TxResponse{TxHash: res.TxHash}, nil
}

// UnjailFinalityProvider sends an unjail transaction to the consumer chain
func (bc *BabylonController) UnjailFinalityProvider(fpPk *btcec.PublicKey) (*types.TxResponse, error) {
msg := &finalitytypes.MsgUnjailFinalityProvider{
Signer: bc.MustGetTxSigner(),
FpBtcPk: bbntypes.NewBIP340PubKeyFromBTCPK(fpPk),
}

unrecoverableErrs := []*sdkErr.Error{
btcstakingtypes.ErrFpNotFound,
btcstakingtypes.ErrFpNotJailed,
btcstakingtypes.ErrFpAlreadySlashed,
}

res, err := bc.reliablySendMsg(msg, emptyErrs, unrecoverableErrs)
if err != nil {
return nil, err
}

return &types.TxResponse{TxHash: res.TxHash}, nil
}

// QueryFinalityProviderSlashedOrJailed - returns if the fp has been slashed, jailed, err
func (bc *BabylonController) QueryFinalityProviderSlashedOrJailed(fpPk *btcec.PublicKey) (bool, bool, error) {
fpPubKey := bbntypes.NewBIP340PubKeyFromBTCPK(fpPk)
res, err := bc.bbnClient.QueryClient.FinalityProvider(fpPubKey.MarshalHex())
if err != nil {
Expand Down
114 changes: 56 additions & 58 deletions finality-provider/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,27 +18,26 @@ import (
)

const (
defaultChainType = "babylon"
defaultLogLevel = zapcore.InfoLevel
defaultLogDirname = "logs"
defaultLogFilename = "fpd.log"
defaultFinalityProviderKeyName = "finality-provider"
DefaultRPCPort = 12581
defaultConfigFileName = "fpd.conf"
defaultNumPubRand = 70000 // support running of 1 week with block production time as 10s
defaultNumPubRandMax = 100000
defaultMinRandHeightGap = 35000
defaultStatusUpdateInterval = 20 * time.Second
defaultRandomInterval = 30 * time.Second
defaultSubmitRetryInterval = 1 * time.Second
defaultFastSyncInterval = 10 * time.Second
defaultSyncFpStatusInterval = 30 * time.Second
defaultFastSyncLimit = 10
defaultFastSyncGap = 3
defaultMaxSubmissionRetries = 20
defaultBitcoinNetwork = "signet"
defaultDataDirname = "data"
defaultMaxNumFinalityProviders = 3
defaultChainType = "babylon"
defaultLogLevel = zapcore.InfoLevel
defaultLogDirname = "logs"
defaultLogFilename = "fpd.log"
defaultFinalityProviderKeyName = "finality-provider"
DefaultRPCPort = 12581
defaultConfigFileName = "fpd.conf"
defaultNumPubRand = 70000 // support running of 1 week with block production time as 10s
defaultNumPubRandMax = 100000
defaultMinRandHeightGap = 35000
defaultBatchSubmissionSize = 1000
defaultStatusUpdateInterval = 20 * time.Second
defaultRandomInterval = 30 * time.Second
defaultSubmitRetryInterval = 1 * time.Second
defaultSyncFpStatusInterval = 30 * time.Second
defaultSignatureSubmissionInterval = 1 * time.Second
defaultMaxSubmissionRetries = 20
defaultBitcoinNetwork = "signet"
defaultDataDirname = "data"
defaultMaxNumFinalityProviders = 3
)

var (
Expand All @@ -55,21 +54,21 @@ 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"`
ChainType string `long:"chaintype" description:"the type of the consumer chain (babylon/OPStackL2/wasm)"`
NumPubRand uint64 `long:"numPubRand" description:"The number of Schnorr public randomness for each commitment"`
NumPubRandMax uint64 `long:"numpubrandmax" description:"The upper bound of the number of Schnorr public randomness for each commitment"`
MinRandHeightGap uint64 `long:"minrandheightgap" description:"The minimum gap between the last committed rand height and the current Babylon block height"`
StatusUpdateInterval time.Duration `long:"statusupdateinterval" description:"The interval between each update of finality-provider status"`
RandomnessCommitInterval time.Duration `long:"randomnesscommitinterval" description:"The interval between each attempt to commit public randomness"`
SubmissionRetryInterval time.Duration `long:"submissionretryinterval" description:"The interval between each attempt to submit finality signature or public randomness after a failure"`
MaxSubmissionRetries uint64 `long:"maxsubmissionretries" description:"The maximum number of retries to submit finality signature or public randomness"`
FastSyncInterval time.Duration `long:"fastsyncinterval" description:"The interval between each try of fast sync, which is disabled if the value is 0"`
FastSyncLimit uint64 `long:"fastsynclimit" description:"The maximum number of blocks to catch up for each fast sync"`
FastSyncGap uint64 `long:"fastsyncgap" description:"The block gap that will trigger the fast sync"`
EOTSManagerAddress string `long:"eotsmanageraddress" description:"The address of the remote EOTS manager; Empty if the EOTS manager is running locally"`
MaxNumFinalityProviders uint32 `long:"maxnumfinalityproviders" description:"The maximum number of finality-provider instances running concurrently within the daemon"`
SyncFpStatusInterval time.Duration `long:"syncfpstatusinterval" description:"The duration of time that it should sync FP status with the client blockchain"`
LogLevel string `long:"loglevel" description:"Logging level for all subsystems" choice:"trace" choice:"debug" choice:"info" choice:"warn" choice:"error" choice:"fatal"`
// ChainType and ChainID (if any) of the chain config identify a consumer chain
ChainType string `long:"chaintype" description:"the type of the consumer chain" choice:"babylon"`
NumPubRand uint32 `long:"numPubRand" description:"The number of Schnorr public randomness for each commitment"`
NumPubRandMax uint32 `long:"numpubrandmax" description:"The upper bound of the number of Schnorr public randomness for each commitment"`
MinRandHeightGap uint32 `long:"minrandheightgap" description:"The minimum gap between the last committed rand height and the current Babylon block height"`
MaxSubmissionRetries uint32 `long:"maxsubmissionretries" description:"The maximum number of retries to submit finality signature or public randomness"`
EOTSManagerAddress string `long:"eotsmanageraddress" description:"The address of the remote EOTS manager; Empty if the EOTS manager is running locally"`
BatchSubmissionSize uint32 `long:"batchsubmissionsize" description:"The size of a batch in one submission"`
MaxNumFinalityProviders uint32 `long:"maxnumfinalityproviders" description:"The maximum number of finality-provider instances running concurrently within the daemon"`
StatusUpdateInterval time.Duration `long:"statusupdateinterval" description:"The interval between each update of finality-provider status"`
RandomnessCommitInterval time.Duration `long:"randomnesscommitinterval" description:"The interval between each attempt to commit public randomness"`
SubmissionRetryInterval time.Duration `long:"submissionretryinterval" description:"The interval between each attempt to submit finality signature or public randomness after a failure"`
SyncFpStatusInterval time.Duration `long:"syncfpstatusinterval" description:"The duration of time that it should sync FP status with the client blockchain"`
SignatureSubmissionInterval time.Duration `long:"signaturesubmissioninterval" description:"The interval between each finality signature(s) submission"`

BitcoinNetwork string `long:"bitcoinnetwork" description:"Bitcoin network to run on" choise:"mainnet" choice:"regtest" choice:"testnet" choice:"simnet" choice:"signet"`

Expand All @@ -96,28 +95,27 @@ func DefaultConfigWithHome(homePath string) Config {
bbnCfg.KeyDirectory = homePath
pollerCfg := DefaultChainPollerConfig()
cfg := Config{
ChainType: defaultChainType,
LogLevel: defaultLogLevel.String(),
DatabaseConfig: DefaultDBConfigWithHomePath(homePath),
BabylonConfig: &bbnCfg,
PollerConfig: &pollerCfg,
NumPubRand: defaultNumPubRand,
NumPubRandMax: defaultNumPubRandMax,
MinRandHeightGap: defaultMinRandHeightGap,
StatusUpdateInterval: defaultStatusUpdateInterval,
RandomnessCommitInterval: defaultRandomInterval,
SubmissionRetryInterval: defaultSubmitRetryInterval,
FastSyncInterval: defaultFastSyncInterval,
FastSyncLimit: defaultFastSyncLimit,
FastSyncGap: defaultFastSyncGap,
MaxSubmissionRetries: defaultMaxSubmissionRetries,
BitcoinNetwork: defaultBitcoinNetwork,
BTCNetParams: defaultBTCNetParams,
EOTSManagerAddress: defaultEOTSManagerAddress,
RpcListener: DefaultRpcListener,
MaxNumFinalityProviders: defaultMaxNumFinalityProviders,
Metrics: metrics.DefaultFpConfig(),
SyncFpStatusInterval: defaultSyncFpStatusInterval,
ChainType: defaultChainType,
LogLevel: defaultLogLevel.String(),
DatabaseConfig: DefaultDBConfigWithHomePath(homePath),
BabylonConfig: &bbnCfg,
PollerConfig: &pollerCfg,
NumPubRand: defaultNumPubRand,
NumPubRandMax: defaultNumPubRandMax,
MinRandHeightGap: defaultMinRandHeightGap,
BatchSubmissionSize: defaultBatchSubmissionSize,
StatusUpdateInterval: defaultStatusUpdateInterval,
RandomnessCommitInterval: defaultRandomInterval,
SubmissionRetryInterval: defaultSubmitRetryInterval,
SignatureSubmissionInterval: defaultSignatureSubmissionInterval,
MaxSubmissionRetries: defaultMaxSubmissionRetries,
BitcoinNetwork: defaultBitcoinNetwork,
BTCNetParams: defaultBTCNetParams,
EOTSManagerAddress: defaultEOTSManagerAddress,
RpcListener: DefaultRpcListener,
Metrics: metrics.DefaultFpConfig(),
SyncFpStatusInterval: defaultSyncFpStatusInterval,
MaxNumFinalityProviders: defaultMaxNumFinalityProviders,
}

if err := cfg.Validate(); err != nil {
Expand Down
4 changes: 2 additions & 2 deletions finality-provider/config/poller.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import "time"

var (
defaultBufferSize = uint32(1000)
defaultPollingInterval = 20 * time.Second
defaultPollingInterval = 1 * time.Second
defaultStaticStartHeight = uint64(1)
)

type ChainPollerConfig struct {
BufferSize uint32 `long:"buffersize" description:"The maximum number of Babylon blocks that can be stored in the buffer"`
PollInterval time.Duration `long:"pollinterval" description:"The interval between each polling of consumer chain blocks"`
PollInterval time.Duration `long:"pollinterval" description:"The interval between each polling of blocks; the value should be set depending on the block production time but could be set smaller for quick catching up"`
StaticChainScanningStartHeight uint64 `long:"staticchainscanningstartheight" description:"The static height from which we start polling the chain"`
AutoChainScanningMode bool `long:"autochainscanningmode" description:"Automatically discover the height from which to start polling the chain"`
}
Expand Down
99 changes: 0 additions & 99 deletions finality-provider/service/fastsync.go

This file was deleted.

Loading

0 comments on commit aaef57e

Please sign in to comment.