mirror of
https://github.com/planetmint/planetmint-go.git
synced 2025-03-30 15:08:28 +00:00
217 pop participant election (#244)
* implemented SelectPopParticipants * added check if enough participants to initiate PoP * make use of lib for broadcasting tx Signed-off-by: Lorenz Herzberger <lorenzherzberger@gmail.com>
This commit is contained in:
parent
c09aab8b38
commit
0cab7d5878
@ -103,3 +103,6 @@ issues:
|
||||
linters:
|
||||
- dupl
|
||||
- paralleltest
|
||||
- path: tests/.*/*\.go
|
||||
linters:
|
||||
- paralleltest
|
||||
|
@ -568,10 +568,12 @@ func New(
|
||||
keys[daomoduletypes.ChallengeKey],
|
||||
keys[daomoduletypes.MintRequestHashKey],
|
||||
keys[daomoduletypes.MintRequestAddressKey],
|
||||
keys[authtypes.StoreKey],
|
||||
app.GetSubspace(daomoduletypes.ModuleName),
|
||||
|
||||
app.BankKeeper,
|
||||
app.AccountKeeper,
|
||||
app.MachineKeeper,
|
||||
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
|
||||
)
|
||||
daoModule := daomodule.NewAppModule(appCodec, app.DaoKeeper, app.AccountKeeper, app.BankKeeper)
|
||||
|
@ -9,7 +9,11 @@ import (
|
||||
)
|
||||
|
||||
func TestE2ETestSuite(t *testing.T) {
|
||||
t.Parallel()
|
||||
cfg := network.DefaultConfig()
|
||||
suite.Run(t, NewE2ETestSuite(cfg))
|
||||
}
|
||||
|
||||
func TestPopE2ETestSuite(t *testing.T) {
|
||||
cfg := network.DefaultConfig()
|
||||
suite.Run(t, NewPopSelectionE2ETestSuite(cfg))
|
||||
}
|
||||
|
130
tests/e2e/dao/pop_participant_selection_suite.go
Normal file
130
tests/e2e/dao/pop_participant_selection_suite.go
Normal file
@ -0,0 +1,130 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/planetmint/planetmint-go/config"
|
||||
"github.com/planetmint/planetmint-go/lib"
|
||||
clitestutil "github.com/planetmint/planetmint-go/testutil/cli"
|
||||
"github.com/planetmint/planetmint-go/testutil/network"
|
||||
"github.com/planetmint/planetmint-go/testutil/sample"
|
||||
daocli "github.com/planetmint/planetmint-go/x/dao/client/cli"
|
||||
machinetypes "github.com/planetmint/planetmint-go/x/machine/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
var machines = []struct {
|
||||
name string
|
||||
mnemonic string
|
||||
address string
|
||||
}{
|
||||
{
|
||||
name: "R2D2",
|
||||
mnemonic: "number judge garbage lock village slush business upset suspect green wrestle puzzle foil tragic drum stereo ticket teach upper bone inject monkey deny portion",
|
||||
address: "plmnt1kp93kns6hs2066d8qw0uz84fw3vlthewt2ck6p",
|
||||
},
|
||||
{
|
||||
name: "C3PO",
|
||||
mnemonic: "letter plate husband impulse grid lake panel seminar try powder virtual run spice siege mutual enhance ripple country two boring have convince symptom fuel",
|
||||
address: "plmnt15wrx9eqegjtlvvx80huau7rkn3f44rdj969xrx",
|
||||
},
|
||||
}
|
||||
|
||||
type PopSelectionE2ETestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
cfg network.Config
|
||||
network *network.Network
|
||||
}
|
||||
|
||||
func NewPopSelectionE2ETestSuite(cfg network.Config) *PopSelectionE2ETestSuite {
|
||||
return &PopSelectionE2ETestSuite{cfg: cfg}
|
||||
}
|
||||
|
||||
func (s *PopSelectionE2ETestSuite) SetupSuite() {
|
||||
s.T().Log("setting up e2e test suite")
|
||||
cfg := config.GetConfig()
|
||||
cfg.FeeDenom = "stake"
|
||||
|
||||
s.network = network.New(s.T(), s.cfg)
|
||||
|
||||
// create 2 machines accounts
|
||||
for i, machine := range machines {
|
||||
s.attestMachine(machine.name, machine.mnemonic, i)
|
||||
}
|
||||
}
|
||||
|
||||
// TearDownSuite clean up after testing
|
||||
func (s *PopSelectionE2ETestSuite) TearDownSuite() {
|
||||
s.T().Log("tearing down e2e test suite")
|
||||
}
|
||||
|
||||
func (s *PopSelectionE2ETestSuite) TestPopSelection() {
|
||||
val := s.network.Validators[0]
|
||||
|
||||
// set PopEpochs to 1 in Order to trigger some participant selections
|
||||
cfg := config.GetConfig()
|
||||
cfg.PopEpochs = 1
|
||||
|
||||
// wait for some blocks so challenges get stored
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
// check if machines are selected as challanger/challengee
|
||||
height, _ := s.network.LatestHeight()
|
||||
queryHeight := height - 1
|
||||
out, err := clitestutil.ExecTestCLICmd(val.ClientCtx, daocli.CmdGetChallenge(), []string{
|
||||
strconv.FormatInt(queryHeight, 10),
|
||||
})
|
||||
s.Require().NoError(err)
|
||||
|
||||
assert.Contains(s.T(), out.String(), machines[0].address)
|
||||
assert.Contains(s.T(), out.String(), machines[1].address)
|
||||
}
|
||||
|
||||
func (s *PopSelectionE2ETestSuite) attestMachine(name string, mnemonic string, num int) {
|
||||
val := s.network.Validators[0]
|
||||
|
||||
kb := val.ClientCtx.Keyring
|
||||
account, err := kb.NewAccount(name, mnemonic, keyring.DefaultBIP39Passphrase, sample.DefaultDerivationPath, hd.Secp256k1)
|
||||
s.Require().NoError(err)
|
||||
|
||||
addr, _ := account.GetAddress()
|
||||
|
||||
// sending funds to machine to initialize account on chain
|
||||
coin := sdk.NewCoins(sdk.NewInt64Coin("stake", 1000))
|
||||
sendMsg := banktypes.NewMsgSend(val.Address, addr, coin)
|
||||
_, err = lib.BroadcastTxWithFileLock(val.Address, sendMsg)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
// register Ta
|
||||
prvKey, pubKey := sample.KeyPair(num)
|
||||
|
||||
ta := sample.TrustAnchor(pubKey)
|
||||
registerMsg := machinetypes.NewMsgRegisterTrustAnchor(val.Address.String(), &ta)
|
||||
_, err = lib.BroadcastTxWithFileLock(val.Address, registerMsg)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
// name and address of private key with which to sign
|
||||
clientCtx := val.ClientCtx.
|
||||
WithFromAddress(addr).
|
||||
WithFromName(name)
|
||||
libConfig := lib.GetConfig()
|
||||
libConfig.SetClientCtx(clientCtx)
|
||||
|
||||
machine := sample.Machine(name, pubKey, prvKey, addr.String())
|
||||
attestMsg := machinetypes.NewMsgAttestMachine(addr.String(), &machine)
|
||||
_, err = lib.BroadcastTxWithFileLock(addr, attestMsg)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NoError(s.network.WaitForNextBlock())
|
||||
|
||||
// reset clientCtx to validator ctx
|
||||
libConfig.SetClientCtx(val.ClientCtx)
|
||||
}
|
@ -64,9 +64,11 @@ func DaoKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) {
|
||||
challengeStoreKey,
|
||||
mintRequestHashStoreKey,
|
||||
mintRequestAddressStoreKey,
|
||||
nil, // TODO: mount and add store/key
|
||||
paramsSubspace,
|
||||
bk,
|
||||
nil,
|
||||
nil,
|
||||
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
|
||||
)
|
||||
|
||||
|
@ -24,12 +24,13 @@ func BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock, k keeper.Keeper)
|
||||
hexProposerAddress := hex.EncodeToString(proposerAddress)
|
||||
if isPopHeight(req.Header.GetHeight()) {
|
||||
// select PoP participants
|
||||
challenger := ""
|
||||
challengee := ""
|
||||
challenger, challengee := k.SelectPopParticipants(ctx)
|
||||
|
||||
// Issue PoP
|
||||
util.SendInitPoP(ctx, hexProposerAddress, challenger, challengee, currentBlockHeight)
|
||||
// TODO send MQTT message to challenger && challengee
|
||||
if challenger != "" && challengee != "" {
|
||||
// Issue PoP
|
||||
util.SendInitPoP(ctx, hexProposerAddress, challenger, challengee, currentBlockHeight)
|
||||
// TODO send MQTT message to challenger && challengee
|
||||
}
|
||||
}
|
||||
|
||||
if isReIssuanceHeight(currentBlockHeight) {
|
||||
|
@ -4,8 +4,10 @@ import (
|
||||
"fmt"
|
||||
|
||||
"cosmossdk.io/math"
|
||||
db "github.com/cometbft/cometbft-db"
|
||||
"github.com/cometbft/cometbft/libs/log"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/store/prefix"
|
||||
storetypes "github.com/cosmos/cosmos-sdk/store/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
@ -25,10 +27,12 @@ type (
|
||||
challengeKey storetypes.StoreKey
|
||||
mintRequestHashKey storetypes.StoreKey
|
||||
mintRequestAddressKey storetypes.StoreKey
|
||||
accountKeeperKey storetypes.StoreKey
|
||||
paramstore paramtypes.Subspace
|
||||
|
||||
bankKeeper types.BankKeeper
|
||||
accountKeeper types.AccountKeeper
|
||||
machineKeeper types.MachineKeeper
|
||||
authority string
|
||||
}
|
||||
)
|
||||
@ -40,10 +44,12 @@ func NewKeeper(
|
||||
challengeKey storetypes.StoreKey,
|
||||
mintRequestHashKey storetypes.StoreKey,
|
||||
mintRequestAddressKey storetypes.StoreKey,
|
||||
accountKeeperKey storetypes.StoreKey,
|
||||
ps paramtypes.Subspace,
|
||||
|
||||
bankKeeper types.BankKeeper,
|
||||
accountKeeper types.AccountKeeper,
|
||||
machineKeeper types.MachineKeeper,
|
||||
authority string,
|
||||
) *Keeper {
|
||||
// set KeyTable if it has not already been set
|
||||
@ -58,10 +64,12 @@ func NewKeeper(
|
||||
challengeKey: challengeKey,
|
||||
mintRequestHashKey: mintRequestHashKey,
|
||||
mintRequestAddressKey: mintRequestAddressKey,
|
||||
accountKeeperKey: accountKeeperKey,
|
||||
paramstore: ps,
|
||||
|
||||
bankKeeper: bankKeeper,
|
||||
accountKeeper: accountKeeper,
|
||||
machineKeeper: machineKeeper,
|
||||
authority: authority,
|
||||
}
|
||||
}
|
||||
@ -143,3 +151,56 @@ func (k Keeper) processBalances(ctx sdk.Context, balances map[string]math.Int, t
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (k Keeper) SelectPopParticipants(ctx sdk.Context) (challenger string, challengee string) {
|
||||
cfg := config.GetConfig()
|
||||
|
||||
var startAccountNumber uint64
|
||||
lastPopHeight := ctx.BlockHeight() - int64(cfg.PopEpochs)
|
||||
lastPop, found := k.LookupChallenge(ctx, lastPopHeight)
|
||||
if lastPopHeight > 0 && found {
|
||||
lastAccountAddr := sdk.MustAccAddressFromBech32(lastPop.Challengee)
|
||||
lastAccount := k.accountKeeper.GetAccount(ctx, lastAccountAddr)
|
||||
startAccountNumber = lastAccount.GetAccountNumber() + 1
|
||||
}
|
||||
|
||||
var participants []sdk.AccAddress
|
||||
k.iterateAccountsForMachines(ctx, startAccountNumber, &participants, true)
|
||||
if len(participants) != 2 {
|
||||
k.iterateAccountsForMachines(ctx, startAccountNumber, &participants, false)
|
||||
}
|
||||
|
||||
// Not enough participants
|
||||
if len(participants) != 2 {
|
||||
return
|
||||
}
|
||||
|
||||
challenger = participants[0].String()
|
||||
challengee = participants[1].String()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (k Keeper) iterateAccountsForMachines(ctx sdk.Context, start uint64, participants *[]sdk.AccAddress, iterateFromStart bool) {
|
||||
store := ctx.KVStore(k.accountKeeperKey)
|
||||
accountStore := prefix.NewStore(store, authtypes.AccountNumberStoreKeyPrefix)
|
||||
var iterator db.Iterator
|
||||
if iterateFromStart {
|
||||
iterator = accountStore.Iterator(sdk.Uint64ToBigEndian(start), nil)
|
||||
} else {
|
||||
iterator = accountStore.Iterator(nil, sdk.Uint64ToBigEndian(start))
|
||||
}
|
||||
defer iterator.Close()
|
||||
|
||||
for ; iterator.Valid(); iterator.Next() {
|
||||
participant := sdk.AccAddress(iterator.Value())
|
||||
_, found := k.machineKeeper.GetMachineIndexByAddress(ctx, participant.String())
|
||||
if found {
|
||||
*participants = append(*participants, participant)
|
||||
}
|
||||
|
||||
if len(*participants) == 2 {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
types "github.com/cosmos/cosmos-sdk/types"
|
||||
types0 "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
types1 "github.com/planetmint/planetmint-go/x/machine/types"
|
||||
)
|
||||
|
||||
// MockAccountKeeper is a mock of AccountKeeper interface.
|
||||
@ -195,3 +196,41 @@ func (mr *MockBankKeeperMockRecorder) SpendableCoins(ctx, addr interface{}) *gom
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SpendableCoins", reflect.TypeOf((*MockBankKeeper)(nil).SpendableCoins), ctx, addr)
|
||||
}
|
||||
|
||||
// MockMachineKeeper is a mock of MachineKeeper interface.
|
||||
type MockMachineKeeper struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockMachineKeeperMockRecorder
|
||||
}
|
||||
|
||||
// MockMachineKeeperMockRecorder is the mock recorder for MockMachineKeeper.
|
||||
type MockMachineKeeperMockRecorder struct {
|
||||
mock *MockMachineKeeper
|
||||
}
|
||||
|
||||
// NewMockMachineKeeper creates a new mock instance.
|
||||
func NewMockMachineKeeper(ctrl *gomock.Controller) *MockMachineKeeper {
|
||||
mock := &MockMachineKeeper{ctrl: ctrl}
|
||||
mock.recorder = &MockMachineKeeperMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockMachineKeeper) EXPECT() *MockMachineKeeperMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// GetMachineIndexByAddress mocks base method.
|
||||
func (m *MockMachineKeeper) GetMachineIndexByAddress(ctx types.Context, address string) (types1.MachineIndex, bool) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetMachineIndexByAddress", ctx, address)
|
||||
ret0, _ := ret[0].(types1.MachineIndex)
|
||||
ret1, _ := ret[1].(bool)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetMachineIndexByAddress indicates an expected call of GetMachineIndexByAddress.
|
||||
func (mr *MockMachineKeeperMockRecorder) GetMachineIndexByAddress(ctx, address interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMachineIndexByAddress", reflect.TypeOf((*MockMachineKeeper)(nil).GetMachineIndexByAddress), ctx, address)
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package types
|
||||
import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
machinetypes "github.com/planetmint/planetmint-go/x/machine/types"
|
||||
)
|
||||
|
||||
// AccountKeeper defines the expected account keeper used for simulations (noalias)
|
||||
@ -24,3 +25,7 @@ type BankKeeper interface {
|
||||
GetBalance(ctx sdk.Context, addr sdk.AccAddress, denom string) sdk.Coin
|
||||
// Methods imported from bank should be defined here
|
||||
}
|
||||
|
||||
type MachineKeeper interface {
|
||||
GetMachineIndexByAddress(ctx sdk.Context, address string) (val machinetypes.MachineIndex, found bool)
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user