Skip to content

Commit

Permalink
Merge branch 'master' into dev/zivkovicmilos/test4-genesis
Browse files Browse the repository at this point in the history
  • Loading branch information
zivkovicmilos committed Jul 7, 2024
2 parents 26f85c1 + b5560e2 commit 28ce66b
Show file tree
Hide file tree
Showing 25 changed files with 881 additions and 143 deletions.
2 changes: 1 addition & 1 deletion contribs/gnodev/pkg/dev/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ func buildNode(logger *slog.Logger, emitter emitter.Emitter, cfg *gnoland.InMemo
func newNodeConfig(tmc *tmcfg.Config, chainid string, appstate gnoland.GnoGenesisState) *gnoland.InMemoryNodeConfig {
// Create Mocked Identity
pv := gnoland.NewMockedPrivValidator()
genesis := gnoland.NewDefaultGenesisConfig(pv.GetPubKey(), chainid)
genesis := gnoland.NewDefaultGenesisConfig(chainid)
genesis.AppState = appstate

// Add self as validator
Expand Down
8 changes: 4 additions & 4 deletions examples/gno.land/r/gov/dao/prop1_filetest.gno
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func main() {
// Status: succeeded
// Author: g1wymu47drhr0kuq2098m792lytgtj2nyx77yrsm
// --
// Valset changes to apply:
// - g12345678 (10)
// - g000000000 (10)
// - g000000000 (0)
// Valset changes:
// - #123: g12345678 (10)
// - #123: g000000000 (10)
// - #123: g000000000 (0)
5 changes: 5 additions & 0 deletions examples/gno.land/r/sys/validators/gno.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
module gno.land/r/sys/validators

require (
gno.land/p/demo/avl v0.0.0-latest
gno.land/p/demo/seqid v0.0.0-latest
gno.land/p/demo/testutils v0.0.0-latest
gno.land/p/demo/uassert v0.0.0-latest
gno.land/p/demo/ufmt v0.0.0-latest
gno.land/p/gov/proposal v0.0.0-latest
gno.land/p/nt/poa v0.0.0-latest
gno.land/p/sys/validators v0.0.0-latest
Expand Down
26 changes: 17 additions & 9 deletions examples/gno.land/r/sys/validators/gnosdk.gno
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
package validators

import "gno.land/p/sys/validators"
import (
"gno.land/p/sys/validators"
)

// getChanges returns the validator changes stored on the realm.
// This function is unexported and intended to be called by gno.land through the GnoSDK
func getChanges() []validators.Validator {
// Construct the changes
valsetChanges := make([]validators.Validator, len(changes))
copy(valsetChanges, changes)
// GetChanges returns the validator changes stored on the realm, since the given block number.
// This function is intended to be called by gno.land through the GnoSDK
func GetChanges(from int64) []validators.Validator {
valsetChanges := make([]validators.Validator, 0)

// Reset the changes set
changes = changes[:0]
// Gather the changes from the specified block
changes.Iterate(getBlockID(from), "", func(_ string, value interface{}) bool {
chs := value.([]change)

for _, ch := range chs {
valsetChanges = append(valsetChanges, ch.validator)
}

return false
})

return valsetChanges
}
4 changes: 2 additions & 2 deletions examples/gno.land/r/sys/validators/init.gno
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
package validators

import (
"gno.land/p/demo/avl"
"gno.land/p/nt/poa"
"gno.land/p/sys/validators"
)

func init() {
// The default valset protocol is PoA
vp = poa.NewPoA()

// No changes to apply initially
changes = make([]validators.Validator, 0)
changes = avl.NewTree()
}
83 changes: 70 additions & 13 deletions examples/gno.land/r/sys/validators/validators.gno
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,24 @@ package validators

import (
"std"
"strconv"

"gno.land/p/demo/avl"
"gno.land/p/demo/seqid"
"gno.land/p/demo/ufmt"
"gno.land/p/sys/validators"
)

var (
vp validators.ValsetProtocol // p is the underlying validator set protocol
changes []validators.Validator // changes are the set changes that happened between scrapes
changes *avl.Tree // changes holds any valset changes; seqid(block number) -> []change
)

// change represents a single valset change, tied to a specific block number
type change struct {
blockNum int64 // the block number associated with the valset change
validator validators.Validator // the validator update
}

// addValidator adds a new validator to the validator set.
// If the validator is already present, the method errors out
func addValidator(validator validators.Validator) {
Expand All @@ -21,7 +29,12 @@ func addValidator(validator validators.Validator) {
}

// Validator added, note the change
changes = append(changes, val)
ch := change{
blockNum: std.GetHeight(),
validator: val,
}

saveChange(ch)

// Emit the validator set change
std.Emit(validators.ValidatorAddedEvent)
Expand All @@ -36,25 +49,69 @@ func removeValidator(address std.Address) {
}

// Validator removed, note the change
changes = append(changes, validators.Validator{
Address: val.Address,
PubKey: val.PubKey,
VotingPower: 0, // nullified the voting power indicates removal
})
ch := change{
blockNum: std.GetHeight(),
validator: validators.Validator{
Address: val.Address,
PubKey: val.PubKey,
VotingPower: 0, // nullified the voting power indicates removal
},
}

saveChange(ch)

// Emit the validator set change
std.Emit(validators.ValidatorRemovedEvent)
}

// saveChange saves the valset change
func saveChange(ch change) {
id := getBlockID(ch.blockNum)

setRaw, exists := changes.Get(id)
if !exists {
changes.Set(id, []change{ch})

return
}

// Save the change
set := setRaw.([]change)
set = append(set, ch)

changes.Set(id, set)
}

// getBlockID converts the block number to a sequential ID
func getBlockID(blockNum int64) string {
return seqid.ID(uint64(blockNum)).String()
}

func Render(_ string) string {
if len(changes) == 0 {
var (
size = changes.Size()
maxDisplay = 10
)

if size == 0 {
return "No valset changes to apply."
}

output := "Valset changes to apply:\n"
for _, change := range changes {
output += "- " + string(change.Address) + " (" + strconv.FormatUint(change.VotingPower, 10) + ")\n"
}
output := "Valset changes:\n"
changes.ReverseIterateByOffset(size-maxDisplay, maxDisplay, func(_ string, value interface{}) bool {
chs := value.([]change)

for _, ch := range chs {
output += ufmt.Sprintf(
"- #%d: %s (%d)\n",
ch.blockNum,
ch.validator.Address.String(),
ch.validator.VotingPower,
)
}

return false
})

return output
}
102 changes: 102 additions & 0 deletions examples/gno.land/r/sys/validators/validators_test.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package validators

import (
"testing"

"std"

"gno.land/p/demo/avl"
"gno.land/p/demo/testutils"
"gno.land/p/demo/uassert"
"gno.land/p/demo/ufmt"
"gno.land/p/sys/validators"
)

// generateTestValidators generates a dummy validator set
func generateTestValidators(count int) []validators.Validator {
vals := make([]validators.Validator, 0, count)

for i := 0; i < count; i++ {
val := validators.Validator{
Address: testutils.TestAddress(ufmt.Sprintf("%d", i)),
PubKey: "public-key",
VotingPower: 10,
}

vals = append(vals, val)
}

return vals
}

func TestValidators_AddRemove(t *testing.T) {
// Clear any changes
changes = avl.NewTree()

var (
vals = generateTestValidators(100)
initialHeight = int64(123)
)

// Add in the validators
for _, val := range vals {
addValidator(val)

// Make sure the validator is added
uassert.True(t, vp.IsValidator(val.Address))

std.TestSkipHeights(1)
}

for i := initialHeight; i < initialHeight+int64(len(vals)); i++ {
// Make sure the changes are saved
chs := GetChanges(i)

// We use the funky index calculation to make sure
// changes are properly handled for each block span
uassert.Equal(t, initialHeight+int64(len(vals))-i, int64(len(chs)))

for index, val := range vals[i-initialHeight:] {
// Make sure the changes are equal to the additions
ch := chs[index]

uassert.Equal(t, val.Address, ch.Address)
uassert.Equal(t, val.PubKey, ch.PubKey)
uassert.Equal(t, val.VotingPower, ch.VotingPower)
}
}

// Save the beginning height for the removal
initialRemoveHeight := std.GetHeight()

// Clear any changes
changes = avl.NewTree()

// Remove the validators
for _, val := range vals {
removeValidator(val.Address)

// Make sure the validator is removed
uassert.False(t, vp.IsValidator(val.Address))

std.TestSkipHeights(1)
}

for i := initialRemoveHeight; i < initialRemoveHeight+int64(len(vals)); i++ {
// Make sure the changes are saved
chs := GetChanges(i)

// We use the funky index calculation to make sure
// changes are properly handled for each block span
uassert.Equal(t, initialRemoveHeight+int64(len(vals))-i, int64(len(chs)))

for index, val := range vals[i-initialRemoveHeight:] {
// Make sure the changes are equal to the additions
ch := chs[index]

uassert.Equal(t, val.Address, ch.Address)
uassert.Equal(t, val.PubKey, ch.PubKey)
uassert.Equal(t, uint64(0), ch.VotingPower)
}
}
}
8 changes: 6 additions & 2 deletions gno.land/cmd/gnoland/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
bft "github.com/gnolang/gno/tm2/pkg/bft/types"
"github.com/gnolang/gno/tm2/pkg/commands"
"github.com/gnolang/gno/tm2/pkg/crypto"
"github.com/gnolang/gno/tm2/pkg/events"
osm "github.com/gnolang/gno/tm2/pkg/os"
"github.com/gnolang/gno/tm2/pkg/telemetry"
"go.uber.org/zap"
Expand Down Expand Up @@ -239,14 +240,17 @@ func execStart(ctx context.Context, c *startCfg, io commands.IO) error {
io.Println(startGraphic)
}

// Create a top-level shared event switch
evsw := events.NewEventSwitch()

// Create application and node
cfg.LocalApp, err = gnoland.NewApp(nodeDir, c.skipFailingGenesisTxs, logger, c.genesisMaxVMCycles)
cfg.LocalApp, err = gnoland.NewApp(nodeDir, c.skipFailingGenesisTxs, evsw, logger)
if err != nil {
return fmt.Errorf("unable to create the Gnoland app, %w", err)
}

// Create a default node, with the given setup
gnoNode, err := node.DefaultNewNode(cfg, genesisPath, logger)
gnoNode, err := node.DefaultNewNode(cfg, genesisPath, evsw, logger)
if err != nil {
return fmt.Errorf("unable to create the Gnoland node, %w", err)
}
Expand Down
Loading

0 comments on commit 28ce66b

Please sign in to comment.