diff --git a/testutil/datagen/raw_checkpoint.go b/testutil/datagen/raw_checkpoint.go index c99ba2633..142d853db 100644 --- a/testutil/datagen/raw_checkpoint.go +++ b/testutil/datagen/raw_checkpoint.go @@ -1,6 +1,8 @@ package datagen import ( + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + sdk "github.com/cosmos/cosmos-sdk/types" "math/rand" "github.com/babylonchain/babylon/btctxformatter" @@ -65,6 +67,61 @@ func GenRandomSequenceRawCheckpointsWithMeta() []*types.RawCheckpointWithMeta { return checkpoints } +func GenerateValidatorSetWithBLSPrivKeys(n int) (types.ValidatorWithBLSSet, []bls12381.PrivateKey) { + var ( + valSet []*types.ValidatorWithBlsKey + blsPrivKeys []bls12381.PrivateKey + ) + + for i := 0; i < n; i++ { + addr := sdk.ValAddress(secp256k1.GenPrivKey().PubKey().Address()) + blsPrivkey := bls12381.GenPrivKey() + val := &types.ValidatorWithBlsKey{ + ValidatorAddress: addr.String(), + BlsPubKey: blsPrivkey.PubKey(), + VotingPower: 1000, + } + valSet = append(valSet, val) + blsPrivKeys = append(blsPrivKeys, blsPrivkey) + } + + return valSet, blsPrivKeys +} + +func GenerateBLSSigs(keys []bls12381.PrivateKey, msg []byte) []bls12381.Signature { + var sigs []bls12381.Signature + for _, privkey := range keys { + sig := bls12381.Sign(privkey, msg) + sigs = append(sigs, sig) + } + + return sigs +} + +func GenerateLegitimateRawCheckpoint(privKeys []bls12381.PrivateKey) *types.RawCheckpoint { + // number of validators, at least 4 + n := len(privKeys) + // ensure sufficient signers + signerNum := n/3 + 1 + epochNum := GenRandomEpochNum() + lch := GenRandomLastCommitHash() + msgBytes := append(sdk.Uint64ToBigEndian(epochNum), lch.MustMarshal()...) + sigs := GenerateBLSSigs(privKeys[:signerNum], msgBytes) + multiSig, _ := bls12381.AggrSigList(sigs) + bm := bitmap.New(13) + for i := 0; i < signerNum; i++ { + bm.Set(i, true) + } + btcCheckpoint := &types.RawCheckpoint{ + EpochNum: epochNum, + LastCommitHash: &lch, + Bitmap: bm, + BlsMultiSig: &multiSig, + } + + return btcCheckpoint +} + func GenRandomEpochNum() uint64 { epochNum := rand.Int63n(100) return uint64(epochNum) diff --git a/x/checkpointing/types/validator_bls_set.go b/x/checkpointing/types/validator_bls_set.go new file mode 100644 index 000000000..e148fe02b --- /dev/null +++ b/x/checkpointing/types/validator_bls_set.go @@ -0,0 +1,46 @@ +package types + +import ( + "errors" + "github.com/babylonchain/babylon/crypto/bls12381" + "github.com/boljen/go-bitmap" +) + +type ValidatorWithBLSSet []*ValidatorWithBlsKey + +// FindSubsetWithPowerSum returns a subset and the sum of the voting Power +// based on the given bitmap +func (ks ValidatorWithBLSSet) FindSubsetWithPowerSum(bm bitmap.Bitmap) (ValidatorWithBLSSet, uint64, error) { + var ( + sum uint64 + valSet ValidatorWithBLSSet + ) + + for i := 0; i < bm.Len(); i++ { + if bm.Get(i) { + if i >= len(ks) { + return valSet, sum, errors.New("invalid validator index") + } + valSet = append(valSet, ks[i]) + sum += ks[i].VotingPower + } + } + return valSet, sum, nil +} + +func (ks ValidatorWithBLSSet) GetBLSKeySet() []bls12381.PublicKey { + var blsKeySet []bls12381.PublicKey + for _, val := range ks { + blsKeySet = append(blsKeySet, val.BlsPubKey) + } + return blsKeySet +} + +func (ks ValidatorWithBLSSet) GetTotalPower() uint64 { + var total uint64 + for _, key := range ks { + total += key.VotingPower + } + + return total +}