Skip to content

Commit

Permalink
Abort query if not enough stake is connected (#3345)
Browse files Browse the repository at this point in the history
Signed-off-by: Yacov Manevich <[email protected]>
  • Loading branch information
yacovm authored Sep 6, 2024
1 parent 718128a commit 6e1a905
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 1 deletion.
24 changes: 23 additions & 1 deletion snow/engine/snowman/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ import (
"github.com/ava-labs/avalanchego/utils/units"
)

const nonVerifiedCacheSize = 64 * units.MiB
const (
nonVerifiedCacheSize = 64 * units.MiB
errInsufficientStake = "insufficient connected stake"
)

var _ common.Engine = (*Engine)(nil)

Expand Down Expand Up @@ -871,6 +874,10 @@ func (e *Engine) sendQuery(
blkBytes []byte,
push bool,
) {
if e.abortDueToInsufficientConnectedStake(blkID) {
return
}

e.Ctx.Log.Verbo("sampling from validators",
zap.Stringer("validators", e.Validators),
)
Expand Down Expand Up @@ -916,6 +923,21 @@ func (e *Engine) sendQuery(
}
}

func (e *Engine) abortDueToInsufficientConnectedStake(blkID ids.ID) bool {
stakeConnectedRatio := e.Config.ConnectedValidators.ConnectedPercent()
minConnectedStakeToQuery := float64(e.Params.AlphaConfidence) / float64(e.Params.K)

if stakeConnectedRatio < minConnectedStakeToQuery {
e.Ctx.Log.Debug("dropped query for block",
zap.String("reason", errInsufficientStake),
zap.Stringer("blkID", blkID),
zap.Float64("ratio", stakeConnectedRatio),
)
return true
}
return false
}

// issue [blk] to consensus
// If [push] is true, a push query will be used. Otherwise, a pull query will be
// used.
Expand Down
39 changes: 39 additions & 0 deletions snow/engine/snowman/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ import (
"github.com/ava-labs/avalanchego/snow/consensus/snowman"
"github.com/ava-labs/avalanchego/snow/consensus/snowman/snowmantest"
"github.com/ava-labs/avalanchego/snow/engine/common"
"github.com/ava-labs/avalanchego/snow/engine/common/tracker"
"github.com/ava-labs/avalanchego/snow/engine/enginetest"
"github.com/ava-labs/avalanchego/snow/engine/snowman/ancestor"
"github.com/ava-labs/avalanchego/snow/engine/snowman/block/blocktest"
"github.com/ava-labs/avalanchego/snow/engine/snowman/getter"
"github.com/ava-labs/avalanchego/snow/snowtest"
"github.com/ava-labs/avalanchego/snow/validators"
"github.com/ava-labs/avalanchego/utils"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/utils/set"
"github.com/ava-labs/avalanchego/version"
)
Expand Down Expand Up @@ -3182,3 +3184,40 @@ func TestShouldIssueBlock(t *testing.T) {
})
}
}

type mockConnVDR struct {
tracker.Peers
percent float64
}

func (m *mockConnVDR) ConnectedPercent() float64 {
return m.percent
}

type logBuffer struct {
bytes.Buffer
}

func (logBuffer) Close() error {
return nil
}

func TestEngineAbortQueryWhenInPartition(t *testing.T) {
require := require.New(t)

// Buffer to record the log entries
buff := logBuffer{}

conf := DefaultConfig(t)
// Overwrite the log to record what it says
conf.Ctx.Log = logging.NewLogger("", logging.NewWrappedCore(logging.Verbo, &buff, logging.Plain.ConsoleEncoder()))
conf.Params = snowball.DefaultParameters
conf.ConnectedValidators = &mockConnVDR{percent: 0.7, Peers: conf.ConnectedValidators}

_, _, _, _, engine := setup(t, conf)

// Gossip will cause a pull query if enough stake is connected
engine.sendQuery(context.Background(), ids.ID{}, nil, false)

require.Contains(buff.String(), errInsufficientStake)
}

0 comments on commit 6e1a905

Please sign in to comment.