Skip to content

Commit

Permalink
test: add apply genesis to testapp and made it deterministic
Browse files Browse the repository at this point in the history
  • Loading branch information
ninabarbakadze committed May 31, 2024
1 parent a3ca919 commit 60861e3
Show file tree
Hide file tree
Showing 6 changed files with 180 additions and 63 deletions.
84 changes: 32 additions & 52 deletions app/test/non_determinism_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,57 +2,45 @@ package app_test

import (
"fmt"
// "os"
"testing"

"github.com/celestiaorg/celestia-app/v2/app"
"github.com/celestiaorg/celestia-app/v2/app/encoding"

"github.com/celestiaorg/celestia-app/v2/pkg/appconsts"
// "github.com/celestiaorg/celestia-app/v2/pkg/user"
testutil "github.com/celestiaorg/celestia-app/v2/test/util"
"github.com/celestiaorg/celestia-app/v2/test/util/blobfactory"
"github.com/celestiaorg/celestia-app/v2/test/util/testfactory"
// "github.com/celestiaorg/celestia-app/v2/test/util/testnode"

// blobtypes "github.com/celestiaorg/celestia-app/v2/x/blob/types"
"github.com/celestiaorg/go-square/blob"
// "github.com/celestiaorg/go-square/namespace"
appns "github.com/celestiaorg/go-square/namespace"
"github.com/cosmos/cosmos-sdk/codec"
hd "github.com/cosmos/cosmos-sdk/crypto/hd"

abci "github.com/tendermint/tendermint/abci/types"

"strconv"

appns "github.com/celestiaorg/go-square/namespace"
keyring "github.com/cosmos/cosmos-sdk/crypto/keyring"
sdk "github.com/cosmos/cosmos-sdk/types"

"github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/stretchr/testify/require"
// tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
abci "github.com/tendermint/tendermint/abci/types"
"testing"
)

func TestNonDeterminismBetweenAppVersions(t *testing.T) {
// set up testapp with genesis state
const (
numBlobTxs, numNormalTxs = 5, 5
account = "test"
)
accounts := deterministicAccounts(numBlobTxs + numNormalTxs)

testApp, _ := testutil.SetupTestAppWithGenesisValSet(app.DefaultConsensusParams())
// ctx := testApp.NewContext(true, tmproto.Header{})

testApp := testutil.NewTestApp()

enc := encoding.MakeConfig(app.ModuleEncodingRegisters...)
accounts = append(accounts, account)
kr, _ := DeterministicKeyRing(enc.Codec, accounts...)
// addr := testfactory.GetAddress(kr, account)
// acc := testutil.DirectQueryAccount(testApp, addr)
// signer, err := user.NewSigner(kr, enc.TxConfig, testutil.ChainID, appconsts.LatestVersion, user.NewAccount(account, acc.GetAccountNumber(), acc.GetSequence()))
// require.NoError(t, err)
accinfos := queryAccountInfo(testApp, accounts, kr)
fmt.Println(kr, "kr")
kr, pubKeys := DeterministicKeyRing(enc.Codec)

var addresses []string

Check failure on line 33 in app/test/non_determinism_test.go

View workflow job for this annotation

GitHub Actions / lint / golangci-lint

Consider pre-allocating `addresses` (prealloc)
krss, _ := kr.List()
// this is for getting names of accounts
for _, account := range krss {
addresses = append(addresses, account.Name)
}

_, _, err := testutil.ApplyGenesisState(testApp, pubKeys, 1_000_000_000, app.DefaultConsensusParams())
require.NoError(t, err)

accinfos := queryAccountInfo(testApp, addresses, kr)

// create deterministic set of 10 transactions
normalTxs := testutil.SendTxsWithAccounts(
Expand All @@ -61,16 +49,18 @@ func TestNonDeterminismBetweenAppVersions(t *testing.T) {
enc.TxConfig,
kr,
1000,
account,
accounts[:numNormalTxs],
addresses[0],
addresses[:numNormalTxs],
testutil.ChainID,
)

fmt.Println(len(accinfos[numBlobTxs:]), "ACCINFOS LENGTH")
fmt.Println(len(addresses[numBlobTxs:]), "ADDRESSES LENGTH")

// maybe change this to signer.CreatePFBS
blobTxs := blobfactory.ManyMultiBlobTx(t, enc.TxConfig, kr, testutil.ChainID, accounts[numBlobTxs:], accinfos[numBlobTxs:], testfactory.Repeat([]*blob.Blob{
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),
}, numBlobTxs))
// normal sdk tx

// deliver normal txs
for _, tx := range normalTxs {
Expand All @@ -95,23 +85,14 @@ func TestNonDeterminismBetweenAppVersions(t *testing.T) {
fmt.Println("AppHash:", appHash)
}

func deterministicAccounts(numAccounts uint64) []string {
const charset = "abcdefghijklmnopqrs"
accounts := make([]string, numAccounts)
for i := range accounts {
accounts[i] = charset + strconv.Itoa(i)
}
return accounts
}

func HardcodedNamespace() 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},
}
}

func DeterministicKeyRing(cdc codec.Codec, accounts ...string) (keyring.Keyring, []sdk.AccAddress) {
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",
"cheap job month trigger flush cactus chest juice dolphin people limit crunch curious secret object beach shield snake hunt group sketch cousin puppy fox",
Expand All @@ -126,18 +107,17 @@ func DeterministicKeyRing(cdc codec.Codec, accounts ...string) (keyring.Keyring,
"charge subway treat loop donate place loan want grief leg message siren joy road exclude match empty enforce vote meadow enlist vintage wool involve",
}
kb := keyring.NewInMemory(cdc)
addresses := make([]sdk.AccAddress, len(accounts))
for idx, acc := range accounts {
rec, err := kb.NewAccount(acc, mnemonics[idx], "", "", hd.Secp256k1)
pubKeys := make([]types.PubKey, len(mnemonics))
for idx, mnemonic := range mnemonics {
rec, err := kb.NewAccount(fmt.Sprintf("account-%d", idx), mnemonic, "", "", hd.Secp256k1)
if err != nil {
panic(err)
}
addr, err := rec.GetAddress()
pubKey, err := rec.GetPubKey()
if err != nil {
panic(err)
}
addresses[idx] = addr

pubKeys[idx] = pubKey
}
return kb, nil
return kb, pubKeys
}
4 changes: 4 additions & 0 deletions app/test/prepare_proposal_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package app_test

import (
// "fmt"
"fmt"
"testing"
"time"

Expand Down Expand Up @@ -209,7 +211,9 @@ func queryAccountInfo(capp *app.App, accs []string, kr keyring.Keyring) []blobfa
infos := make([]blobfactory.AccountInfo, len(accs))
for i, acc := range accs {
addr := testfactory.GetAddress(kr, acc)
fmt.Println(addr, "ADDR")
accI := testutil.DirectQueryAccount(capp, addr)
fmt.Println(accI, "ACC INFO")
infos[i] = blobfactory.AccountInfo{
AccountNum: accI.GetAccountNumber(),
Sequence: accI.GetSequence(),
Expand Down
48 changes: 46 additions & 2 deletions test/util/genesis/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func (g *Genesis) WithGenesisTime(genesisTime time.Time) *Genesis {

func (g *Genesis) WithValidators(vals ...Validator) *Genesis {
for _, val := range vals {
err := g.AddValidator(val)
err := g.NewValidator(val)
if err != nil {
panic(err)
}
Expand Down Expand Up @@ -139,7 +139,7 @@ func (g *Genesis) NewAccount(acc KeyringAccount) error {
return nil
}

func (g *Genesis) AddValidator(val Validator) error {
func (g *Genesis) NewValidator(val Validator) error {
if err := val.ValidateBasic(); err != nil {
return err
}
Expand All @@ -161,6 +161,50 @@ func (g *Genesis) AddValidator(val Validator) error {
return nil
}

// TODO improve this function to imply that we're just adding one validator to make it deterministic
func (g *Genesis) AddValidator(val Validator) error {
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"
rec, err := g.kr.NewAccount("validator1", mnemo, "", "", hd.Secp256k1)
if err != nil {
return err
}
validatorPubKey, err := rec.GetPubKey()
if err != nil {
return err
}

if err := val.ValidateBasic(); err != nil {
return err
}

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

if err := g.AddAccount(account); err != nil {
return err
}

// TODO decide on this
// add validator to genesis keyring
// if _, err := g.kr.Key(val.Name); err == nil {
// return fmt.Errorf("validator with name %s already exists", val.Name)
// }

// // Add the validator's genesis transaction
gentx, err := val.GenTx(g.ecfg, g.kr, g.ChainID)
if 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
}
Expand Down
99 changes: 94 additions & 5 deletions test/util/test_app.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package util

import (
// "bytes"
"encoding/json"
"fmt"
"testing"
Expand All @@ -12,22 +11,24 @@ import (
"github.com/celestiaorg/celestia-app/v2/pkg/appconsts"
v1 "github.com/celestiaorg/celestia-app/v2/pkg/appconsts/v1"
v2 "github.com/celestiaorg/celestia-app/v2/pkg/appconsts/v2"
"github.com/celestiaorg/celestia-app/v2/test/util/genesis"
"github.com/celestiaorg/celestia-app/v2/test/util/testfactory"
"github.com/celestiaorg/celestia-app/v2/test/util/testnode"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
"github.com/cosmos/cosmos-sdk/server"
"github.com/cosmos/cosmos-sdk/simapp"
"github.com/tendermint/tendermint/crypto/ed25519"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
"github.com/spf13/cast"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/crypto/ed25519"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmversion "github.com/tendermint/tendermint/proto/tendermint/version"
Expand Down Expand Up @@ -75,23 +76,111 @@ func SetupTestAppWithGenesisValSet(cparams *tmproto.ConsensusParams, genAccounts
return testApp, kr
}

func NewTestAppWithGenesisSet(cparams *tmproto.ConsensusParams, genAccounts ...string) (*app.App, *tmtypes.ValidatorSet, keyring.Keyring) {
// var cache sdk.MultiStorePersistentCache
func NewTestApp() *app.App {
// EmptyAppOptions is a stub implementing AppOptions
emptyOpts := EmptyAppOptions{}
// var anteOpt = func(bapp *baseapp.BaseApp) { bapp.SetAnteHandler(nil) }
db := dbm.NewMemDB()

encCfg := encoding.MakeConfig(app.ModuleEncodingRegisters...)

testApp := app.New(
return app.New(
log.NewNopLogger(), db, nil,
cast.ToUint(emptyOpts.Get(server.FlagInvCheckPeriod)),
encCfg,
0,
emptyOpts,
)
}

func ApplyGenesisState(testApp *app.App, pubKeys []cryptotypes.PubKey, balance int64, cparams *tmproto.ConsensusParams) (keyring.Keyring, []genesis.Account, error) {
// create genesis
gen := genesis.NewDefaultGenesis().WithChainID("test").WithConsensusParams(cparams).WithGenesisTime(time.Date(2023, 1, 1, 1, 1, 1, 1, time.UTC).UTC())

for _, pk := range pubKeys {
err := gen.AddAccount(genesis.Account{
PubKey: pk,
Balance: balance,
})
if err != nil {
return nil, nil, err
}
}

// hardcoding keys to make validator creation deterministic
consensusKey := ed25519.PrivKey(ed25519.GenPrivKeyFromSecret([]byte("12345678901234567890123456389012")))

Check failure on line 111 in test/util/test_app.go

View workflow job for this annotation

GitHub Actions / lint / golangci-lint

unnecessary conversion (unconvert)
networkKey := ed25519.PrivKey(ed25519.GenPrivKeyFromSecret([]byte("12345678901234567890123456786012")))

Check failure on line 112 in test/util/test_app.go

View workflow job for this annotation

GitHub Actions / lint / golangci-lint

unnecessary conversion (unconvert)

// question: do we want to add validator in the keyring?
err := gen.AddValidator(genesis.Validator{
KeyringAccount: genesis.KeyringAccount{
Name: "validator1",
InitialTokens: 1_000_000_000,
},
Stake: 1_000_000,
ConsensusKey: consensusKey,
NetworkKey: networkKey,
})
if err != nil {
return nil, nil, err
}

genDoc, err := gen.Export()

if err != nil {
return nil, nil, err
}

// initialise test app against genesis
_ = testApp.Info(abci.RequestInfo{})

abciParams := &abci.ConsensusParams{
Block: &abci.BlockParams{
// choose some value large enough to not bottleneck the max square
// size
MaxBytes: int64(appconsts.DefaultSquareSizeUpperBound*appconsts.DefaultSquareSizeUpperBound) * appconsts.ContinuationSparseShareContentSize,
MaxGas: cparams.Block.MaxGas,
},
Evidence: &cparams.Evidence,
Validator: &cparams.Validator,
Version: &cparams.Version,
}

// init chain will set the validator set and initialize the genesis accounts
fmt.Println(genDoc.GenesisTime, "GENDOC APP STATE")

fmt.Println(abciParams, "ABCI PARAMS")
fmt.Println(genDoc.ChainID, "CHAIN ID")

// TODO Understand why genDoc.GenesisTime is getting reset
testApp.InitChain(
abci.RequestInitChain{
Time: gen.GenesisTime,
Validators: []abci.ValidatorUpdate{},
ConsensusParams: abciParams,
AppStateBytes: genDoc.AppState,
ChainId: genDoc.ChainID,
},
)

// commit genesis changes
testApp.Commit()
testApp.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{
ChainID: ChainID,
Height: testApp.LastBlockHeight() + 1,
AppHash: testApp.LastCommitID().Hash,
ValidatorsHash: genDoc.ValidatorHash(),
NextValidatorsHash: genDoc.ValidatorHash(),
Version: tmversion.Consensus{
App: cparams.Version.AppVersion,
},
}})

return gen.Keyring(), gen.Accounts(), nil
}

func NewTestAppWithGenesisSet(cparams *tmproto.ConsensusParams, genAccounts ...string) (*app.App, *tmtypes.ValidatorSet, keyring.Keyring) {
testApp := NewTestApp()
genesisState, valSet, kr := GenesisStateWithSingleValidator(testApp, genAccounts...)

stateBytes, err := json.MarshalIndent(genesisState, "", " ")
Expand Down
1 change: 1 addition & 0 deletions test/util/testfactory/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package testfactory

import (
"bytes"
// "fmt"
"sort"

"github.com/celestiaorg/celestia-app/v2/pkg/appconsts"
Expand Down
Loading

0 comments on commit 60861e3

Please sign in to comment.