mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-22 14:44:30 +00:00
* revert: use masternodes from snapshot to verify vote * fix underflow during chain initialization * add previously removed test * rename snapshot > snap for consistency
124 lines
3.2 KiB
Go
124 lines
3.2 KiB
Go
package engine_v2
|
|
|
|
import (
|
|
"context"
|
|
"log/slog"
|
|
"math/big"
|
|
"sync"
|
|
"testing"
|
|
|
|
"github.com/XinFinOrg/XDPoSChain/common"
|
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
|
"github.com/XinFinOrg/XDPoSChain/params"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
// memoryHandler captures log records for inspection in tests.
|
|
type memoryHandler struct {
|
|
mu sync.Mutex
|
|
attrs []slog.Attr
|
|
records []slog.Record
|
|
}
|
|
|
|
func newMemoryHandler() *memoryHandler {
|
|
return &memoryHandler{}
|
|
}
|
|
|
|
func (h *memoryHandler) Enabled(_ context.Context, _ slog.Level) bool { return true }
|
|
|
|
func (h *memoryHandler) Handle(_ context.Context, r slog.Record) error {
|
|
clone := r.Clone()
|
|
h.mu.Lock()
|
|
defer h.mu.Unlock()
|
|
h.records = append(h.records, clone)
|
|
return nil
|
|
}
|
|
|
|
func (h *memoryHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
|
|
return &memoryHandler{attrs: append(append([]slog.Attr{}, h.attrs...), attrs...)}
|
|
}
|
|
|
|
func (h *memoryHandler) WithGroup(_ string) slog.Handler { return h }
|
|
|
|
func (h *memoryHandler) Records() []slog.Record {
|
|
h.mu.Lock()
|
|
defer h.mu.Unlock()
|
|
out := make([]slog.Record, len(h.records))
|
|
copy(out, h.records)
|
|
return out
|
|
}
|
|
|
|
// MockChainReader is a mock implementation of consensus.ChainReader
|
|
type MockChainReader struct {
|
|
headers map[common.Hash]*types.Header
|
|
}
|
|
|
|
// NewMockChainReader creates a new mock chain reader
|
|
func NewMockChainReader() *MockChainReader {
|
|
return &MockChainReader{
|
|
headers: make(map[common.Hash]*types.Header),
|
|
}
|
|
}
|
|
|
|
// AddHeader adds a header to the mock chain
|
|
func (m *MockChainReader) AddHeader(header *types.Header) {
|
|
m.headers[header.Hash()] = header
|
|
}
|
|
|
|
// Config implements consensus.ChainReader
|
|
func (m *MockChainReader) Config() *params.ChainConfig {
|
|
return nil
|
|
}
|
|
|
|
// CurrentHeader implements consensus.ChainReader
|
|
func (m *MockChainReader) CurrentHeader() *types.Header {
|
|
return nil
|
|
}
|
|
|
|
// GetHeader implements consensus.ChainReader
|
|
func (m *MockChainReader) GetHeader(hash common.Hash, number uint64) *types.Header {
|
|
return nil
|
|
}
|
|
|
|
// GetHeaderByNumber implements consensus.ChainReader
|
|
func (m *MockChainReader) GetHeaderByNumber(number uint64) *types.Header {
|
|
return nil
|
|
}
|
|
|
|
// GetHeaderByHash implements consensus.ChainReader
|
|
func (m *MockChainReader) GetHeaderByHash(hash common.Hash) *types.Header {
|
|
return m.headers[hash]
|
|
}
|
|
|
|
// GetBlock implements consensus.ChainReader
|
|
func (m *MockChainReader) GetBlock(hash common.Hash, number uint64) *types.Block {
|
|
return nil
|
|
}
|
|
|
|
// TestVerifyVoteMessage_VoteRoundTooOld tests that votes with rounds below
|
|
// the current round are rejected immediately
|
|
func TestVerifyVoteMessage_VoteRoundTooOld(t *testing.T) {
|
|
mockChain := NewMockChainReader()
|
|
|
|
engine := &XDPoS_v2{
|
|
currentRound: 10,
|
|
lock: sync.RWMutex{},
|
|
}
|
|
|
|
// Create a vote with a round number less than current round
|
|
vote := &types.Vote{
|
|
ProposedBlockInfo: &types.BlockInfo{
|
|
Hash: common.StringToHash("some-block"),
|
|
Round: 5, // Less than currentRound (10)
|
|
Number: big.NewInt(50),
|
|
},
|
|
Signature: make([]byte, 65),
|
|
GapNumber: 0,
|
|
}
|
|
|
|
verified, err := engine.VerifyVoteMessage(mockChain, vote)
|
|
|
|
// Should reject the vote without error
|
|
assert.False(t, verified, "Should return false for vote with round < currentRound")
|
|
assert.NoError(t, err, "Should not return an error for old round votes")
|
|
}
|