Skip to content

Commit

Permalink
refactor: move some logic from genesis to testapp
Browse files Browse the repository at this point in the history
  • Loading branch information
ninabarbakadze committed Jun 3, 2024
1 parent c0452be commit 60edfd3
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 88 deletions.
39 changes: 23 additions & 16 deletions app/test/non_determinism_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,33 +20,38 @@ import (
abci "github.com/tendermint/tendermint/abci/types"
)

func TestNonDeterminismBetweenAppVersions(t *testing.T) {
// set up testapp with genesis state
// TestNonDeterminismBetweenMainAndV1 executes a set of different transactions,
// produces an app hash and compares it with the app hash produced by v1.x
func TestNonDeterminismBetweenMainAndV1(t *testing.T) {
const (
numBlobTxs, numNormalTxs = 5, 5
)

expectedAppHash := []byte{100, 237, 125, 126, 116, 10, 189, 82, 156, 116, 176, 136, 169, 92, 185, 12, 72, 134, 254, 175, 234, 13, 159, 90, 139, 192, 190, 248, 67, 9, 32, 217}

// initialize testApp
testApp := testutil.NewTestApp()

enc := encoding.MakeConfig(app.ModuleEncodingRegisters...)
// create deterministic keys
kr, pubKeys := DeterministicKeyRing(enc.Codec)

var addresses []string
krss, _ := kr.List()
// this is for getting names of accounts
for _, account := range krss {
addresses = append(addresses, account.Name)
recs, err := kr.List()
require.NoError(t, err)

// Get the name of the records
for _, rec := range recs {
addresses = append(addresses, rec.Name)
}

_, _, err := testutil.ApplyGenesisState(testApp, pubKeys, 1_000_000_000, app.DefaultInitialConsensusParams())
// Apply genesis state to the app
_, _, err = testutil.ApplyGenesisState(testApp, pubKeys, 1_000_000_000, app.DefaultInitialConsensusParams())
require.NoError(t, err)

accinfos := queryAccountInfo(testApp, addresses, kr)
fmt.Println("AccountInfos:", accinfos)

// create deterministic set of 10 transactions
// Create a set of 10 deterministic sdk transactions
normalTxs := testutil.SendTxsWithAccounts(
t,
testApp,
Expand All @@ -58,20 +63,19 @@ func TestNonDeterminismBetweenAppVersions(t *testing.T) {
testutil.ChainID,
)

// maybe change this to signer.CreatePFBS
// Create a set of 5 deterministic blob transactions
blobTxs := blobfactory.ManyMultiBlobTx(t, enc.TxConfig, kr, testutil.ChainID, addresses[numBlobTxs+1:], accinfos[numBlobTxs+1:], testfactory.Repeat([]*blob.Blob{
blob.New(HardcodedNamespace(), []byte{1}, appconsts.DefaultShareVersion),
blob.New(DeterministicNamespace(), []byte{1}, appconsts.DefaultShareVersion),
}, numBlobTxs))

// deliver normal txs
// Deliver sdk txs
for _, tx := range normalTxs {
resp := testApp.DeliverTx(abci.RequestDeliverTx{Tx: tx})
require.EqualValues(t, 0, resp.Code, resp.Log)
}

// deliver blob txs
// Deliver blob txs
for _, tx := range blobTxs {
// fmt.Println("BlobTx:", tx)
blobTx, ok := blob.UnmarshalBlobTx(tx)
require.True(t, ok)
resp := testApp.DeliverTx(abci.RequestDeliverTx{Tx: blobTx.Tx})
Expand All @@ -81,19 +85,22 @@ func TestNonDeterminismBetweenAppVersions(t *testing.T) {
// Commit the state
testApp.Commit()

// // Get the app hash
// Get the app hash
appHash := testApp.LastCommitID().Hash

// Assert that the app hash is equal to the app hash produced by v1.x
require.Equal(t, expectedAppHash, appHash)
}

func HardcodedNamespace() appns.Namespace {
// DeterministicNamespace returns a deterministic namespace
func DeterministicNamespace() appns.Namespace {
return appns.Namespace{
Version: 0,
ID: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 67, 154, 200, 228, 130, 74, 147, 162, 11},
}
}

// DeterministicKeyRing returns a deterministic keyring and a list of deterministic public keys
func DeterministicKeyRing(cdc codec.Codec) (keyring.Keyring, []types.PubKey) {
mnemonics := []string{
"great myself congress genuine scale muscle view uncover pipe miracle sausage broccoli lonely swap table foam brand turtle comic gorilla firm mad grunt hazard",
Expand Down
100 changes: 31 additions & 69 deletions test/util/genesis/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,21 @@ type Genesis struct {
genOps []Modifier
}

// Accounts getter
func (g *Genesis) Accounts() []Account {
return g.accounts
}

// Keyring getter
func (g *Genesis) Keyring() keyring.Keyring {
return g.kr
}

// Validators getter
func (g *Genesis) Validators() []Validator {
return g.validators
}

// NewDefaultGenesis creates a new default genesis with no accounts or validators.
func NewDefaultGenesis() *Genesis {
ecfg := encoding.MakeConfig(app.ModuleBasics)
Expand All @@ -59,26 +74,31 @@ func NewDefaultGenesis() *Genesis {
return g
}

// WithModifier adds a genesis modifier to the genesis.
func (g *Genesis) WithModifiers(ops ...Modifier) *Genesis {
g.genOps = append(g.genOps, ops...)
return g
}

// WithConsensusParams sets the consensus parameters of the genesis.
func (g *Genesis) WithConsensusParams(params *tmproto.ConsensusParams) *Genesis {
g.ConsensusParams = params
return g
}

// WithChainID sets the chain ID of the genesis.
func (g *Genesis) WithChainID(chainID string) *Genesis {
g.ChainID = chainID
return g
}

// WithGenesisTime sets the genesis time of the genesis.
func (g *Genesis) WithGenesisTime(genesisTime time.Time) *Genesis {
g.GenesisTime = genesisTime
return g
}

// WithAccounts adds the given validators to the genesis.
func (g *Genesis) WithValidators(vals ...Validator) *Genesis {
for _, val := range vals {
err := g.NewValidator(val)
Expand All @@ -101,6 +121,7 @@ func (g *Genesis) WithKeyringAccounts(accs ...KeyringAccount) *Genesis {
return g
}

// AddAccount adds an existing account to the genesis.
func (g *Genesis) AddAccount(account Account) error {
for _, acc := range g.accounts {
if bytes.Equal(acc.PubKey.Bytes(), account.PubKey.Bytes()) {
Expand All @@ -111,6 +132,7 @@ func (g *Genesis) AddAccount(account Account) error {
return nil
}

// NewAccount creates a new account and adds it to the genesis.
func (g *Genesis) NewAccount(acc KeyringAccount) error {
if err := acc.ValidateBasic(); err != nil {
return err
Expand Down Expand Up @@ -140,16 +162,12 @@ func (g *Genesis) NewAccount(acc KeyringAccount) error {
return nil
}

func (g *Genesis) NewValidator(val Validator) error {
// AddValidator verifies and adds a given validator to the genesis.
func (g *Genesis) AddValidator(val Validator) error {
if err := val.ValidateBasic(); err != nil {
return err
}

// Add the validator's genesis account
if err := g.NewAccount(val.KeyringAccount); err != nil {
return err
}

// Add the validator's genesis transaction
gentx, err := val.GenTx(g.ecfg, g.kr, g.ChainID)
if err != nil {
Expand All @@ -162,65 +180,17 @@ func (g *Genesis) NewValidator(val Validator) error {
return nil
}

// AddDeterministicValidator adds a single validator to the genesis deterministically.
func (g *Genesis) AddDeterministicValidator() error {
// hardcoded keys for deterministic account creation
mnemo := "body world north giggle crop reduce height copper damp next verify orphan lens loan adjust inform utility theory now ranch motion opinion crowd fun"
consensusKey := ed25519.PrivKey(ed25519.GenPrivKeyFromSecret([]byte("12345678901234567890123456389012")))
networkKey := ed25519.PrivKey(ed25519.GenPrivKeyFromSecret([]byte("12345678901234567890123456786012")))

val := Validator{
KeyringAccount: KeyringAccount{
Name: "validator1",
InitialTokens: 1_000_000_000,
},
Stake: 1_000_000,
ConsensusKey: consensusKey,
NetworkKey: networkKey,
}

// initialize the validator's genesis account in the keyring
rec, err := g.kr.NewAccount(val.Name, mnemo, "", "", hd.Secp256k1)
if err != nil {
return fmt.Errorf("failed to create account: %w", err)
}

validatorPubKey, err := rec.GetPubKey()
if err != nil {
return fmt.Errorf("failed to get pubkey: %w", err)
}

if err := val.ValidateBasic(); err != nil {
return fmt.Errorf("failed to validate validator: %w", err)
}

// make account from keyring account
account := Account{
PubKey: validatorPubKey,
Balance: val.KeyringAccount.InitialTokens,
}

// add the validator's account to the genesis
if err := g.AddAccount(account); err != nil {
return fmt.Errorf("failed to add account: %w", err)
}

// add the validator's genesis transaction
gentx, err := val.GenTx(g.ecfg, g.kr, g.ChainID)
if err != nil {
return fmt.Errorf("failed to generate tx: %w", err)
// Creates a new validator account and adds it to the genesis.
func (g *Genesis) NewValidator(val Validator) error {
// Add the validator's genesis account
if err := g.NewAccount(val.KeyringAccount); err != nil {
return err
}

// install the validator
g.genTxs = append(g.genTxs, gentx)
g.validators = append(g.validators, val)
return nil
}

func (g *Genesis) Accounts() []Account {
return g.accounts
return g.AddValidator(val)
}

// Export returns the genesis document of the network.
func (g *Genesis) Export() (*coretypes.GenesisDoc, error) {
gentxs := make([]json.RawMessage, 0, len(g.genTxs))
for _, genTx := range g.genTxs {
Expand All @@ -242,14 +212,6 @@ func (g *Genesis) Export() (*coretypes.GenesisDoc, error) {
)
}

func (g *Genesis) Keyring() keyring.Keyring {
return g.kr
}

func (g *Genesis) Validators() []Validator {
return g.validators
}

// Validator returns the validator at the given index. False is returned if the
// index is out of bounds.
func (g *Genesis) Validator(i int) (Validator, bool) {
Expand Down
48 changes: 46 additions & 2 deletions test/util/test_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
hd "github.com/cosmos/cosmos-sdk/crypto/hd"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
Expand Down Expand Up @@ -113,7 +114,7 @@ func ApplyGenesisState(testApp *app.App, pubKeys []cryptotypes.PubKey, balance i
}

// add validator to genesis
err := gen.AddDeterministicValidator()
err := AddDeterministicValidatorToGenesis(gen)
if err != nil {
return nil, nil, fmt.Errorf("failed to add validator: %w", err)
}
Expand Down Expand Up @@ -165,6 +166,7 @@ func ApplyGenesisState(testApp *app.App, pubKeys []cryptotypes.PubKey, balance i
return gen.Keyring(), gen.Accounts(), nil
}

// NewTestAppWithGenesisSet initializes a new app with a validator set and genesis accounts.
func NewTestAppWithGenesisSet(cparams *tmproto.ConsensusParams, genAccounts ...string) (*app.App, *tmtypes.ValidatorSet, keyring.Keyring) {
testApp := NewTestApp()
genesisState, valSet, kr := GenesisStateWithSingleValidator(testApp, genAccounts...)
Expand Down Expand Up @@ -203,6 +205,48 @@ func NewTestAppWithGenesisSet(cparams *tmproto.ConsensusParams, genAccounts ...s
return testApp, valSet, kr
}

// AddDeterministicValidatorToGenesis adds a single deterministic validator to the genesis.
func AddDeterministicValidatorToGenesis(g *genesis.Genesis) error {
// hardcoded keys for deterministic account creation
mnemo := "body world north giggle crop reduce height copper damp next verify orphan lens loan adjust inform utility theory now ranch motion opinion crowd fun"
consensusKey := ed25519.GenPrivKeyFromSecret([]byte("12345678901234567890123456389012"))
networkKey := ed25519.GenPrivKeyFromSecret([]byte("12345678901234567890123456786012"))

val := genesis.Validator{
KeyringAccount: genesis.KeyringAccount{
Name: "validator1",
InitialTokens: 1_000_000_000,
},
Stake: 1_000_000,
ConsensusKey: consensusKey,
NetworkKey: networkKey,
}

// initialize the validator's genesis account in the keyring
rec, err := g.Keyring().NewAccount(val.Name, mnemo, "", "", hd.Secp256k1)
if err != nil {
return fmt.Errorf("failed to create account: %w", err)
}

validatorPubKey, err := rec.GetPubKey()
if err != nil {
return fmt.Errorf("failed to get pubkey: %w", err)
}

// make account from keyring account
account := genesis.Account{
PubKey: validatorPubKey,
Balance: val.KeyringAccount.InitialTokens,
}

// add the validator's account to the genesis
if err := g.AddAccount(account); err != nil {
return fmt.Errorf("failed to add account: %w", err)
}

return g.AddValidator(val)
}

// AddAccount mimics the cli addAccount command, providing an
// account with an allocation of to "token" and "tia" tokens in the genesis
// state
Expand Down Expand Up @@ -292,7 +336,7 @@ func GenesisStateWithSingleValidator(testApp *app.App, genAccounts ...string) (a
// create a new keyring with the generated accounts
kr, addresses := testnode.NewKeyring(genAccounts...)
// fund the accounts
fundedBankAccs, fundedAuthAccs := testnode.FundKeyringAccounts(kr, addresses)
fundedBankAccs, fundedAuthAccs := testnode.FundKeyringAccounts(addresses)
accs = append(accs, fundedAuthAccs...)
balances = append(balances, fundedBankAccs...)

Expand Down
2 changes: 1 addition & 1 deletion test/util/testnode/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func RandomAddress() sdk.Address {
return addresses[0]
}

func FundKeyringAccounts(kr keyring.Keyring, addresses []sdk.AccAddress) ([]banktypes.Balance, []authtypes.GenesisAccount) {
func FundKeyringAccounts(addresses []sdk.AccAddress) ([]banktypes.Balance, []authtypes.GenesisAccount) {
genAccounts := make([]authtypes.GenesisAccount, len(addresses))
genBalances := make([]banktypes.Balance, len(addresses))

Expand Down

0 comments on commit 60edfd3

Please sign in to comment.