Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
7d8d855
eth: implemented peer consensus based witness verification
pratikspatil024 Sep 15, 2025
fc81044
eth/fetcher: update peer drop mechanism
pratikspatil024 Sep 25, 2025
96ab269
Merge branch 'develop' of https://github.com/maticnetwork/bor into ps…
pratikspatil024 Sep 25, 2025
e94a428
eth: added dynamic page limit for witness based on gas limit
pratikspatil024 Sep 30, 2025
9515bd1
eth: fix lint
pratikspatil024 Sep 30, 2025
d327194
eth: download witness within limit and block for verificatio
pratikspatil024 Sep 30, 2025
8723b42
eth: fix lint
pratikspatil024 Sep 30, 2025
83ab606
eth, core: added a check to fix a potential vulnerability and added t…
pratikspatil024 Oct 1, 2025
3a6ab74
eth, core: include the original peer in the consenses to get consense…
pratikspatil024 Oct 1, 2025
439e927
eth: implemented RequestWitnessPageCount
pratikspatil024 Oct 1, 2025
e77b139
eth: implemented wit/2 and added new message type to get the witness …
pratikspatil024 Oct 3, 2025
a1703bb
Merge branch 'develop' of https://github.com/maticnetwork/bor into ps…
pratikspatil024 Oct 3, 2025
9f1fd71
eth: updated mock file
pratikspatil024 Oct 3, 2025
d9f0371
eth: removed code duplication
pratikspatil024 Oct 15, 2025
ba40cb6
eth: dropping peer immediately when page count verification fails
pratikspatil024 Oct 15, 2025
5cb56b4
eth: added more comments
pratikspatil024 Oct 15, 2025
6b8d178
Merge branch 'develop' of https://github.com/maticnetwork/bor into ps…
pratikspatil024 Oct 15, 2025
fabf132
Merge branch 'develop' of https://github.com/maticnetwork/bor into ps…
pratikspatil024 Oct 27, 2025
bb5c8fe
Merge branch 'develop' of https://github.com/maticnetwork/bor into ps…
pratikspatil024 Oct 31, 2025
2982663
Merge branch 'develop' of https://github.com/maticnetwork/bor into ps…
pratikspatil024 Nov 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
187 changes: 187 additions & 0 deletions core/stateless/witness_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package stateless
import (
"math/big"
"testing"
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
Expand Down Expand Up @@ -256,3 +257,189 @@ func TestValidateWitnessPreState_MultipleHeaders(t *testing.T) {
t.Errorf("Expected validation to succeed with multiple headers, but got error: %v", err)
}
}

// TestWitnessVerificationConstants tests the verification constants
func TestWitnessVerificationConstants(t *testing.T) {
// These constants should match the ones defined in eth/fetcher/witness_manager.go
const (
witnessPageWarningThreshold = 10
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be better to make this a dynamic parameter based on the block gas limit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

witnessVerificationPeers = 2
)

if witnessPageWarningThreshold != 10 {
t.Errorf("Expected witnessPageWarningThreshold to be 10, got %d", witnessPageWarningThreshold)
}
if witnessVerificationPeers != 2 {
t.Errorf("Expected witnessVerificationPeers to be 2, got %d", witnessVerificationPeers)
}
}

// TestWitnessPageCountVerification tests the page count verification logic
func TestWitnessPageCountVerification(t *testing.T) {
tests := []struct {
name string
reportedPages uint64
peerPages []uint64
expectedHonest bool
description string
}{
{
name: "UnderThreshold_ShouldBeHonest",
reportedPages: 5,
peerPages: []uint64{5, 5},
expectedHonest: true,
description: "Page count under threshold should be considered honest",
},
{
name: "OverThreshold_ConsensusAgreement",
reportedPages: 15,
peerPages: []uint64{15, 15},
expectedHonest: true,
description: "Consensus agreement should mark peer as honest",
},
{
name: "OverThreshold_ConsensusDisagreement",
reportedPages: 15,
peerPages: []uint64{20, 20},
expectedHonest: false,
description: "Consensus disagreement should mark peer as dishonest",
},
{
name: "OverThreshold_MixedResults",
reportedPages: 15,
peerPages: []uint64{15, 20},
expectedHonest: true,
description: "Mixed results should default to honest (conservative)",
},
{
name: "OverThreshold_InsufficientPeers",
reportedPages: 15,
peerPages: []uint64{15},
expectedHonest: true,
description: "Insufficient peers should default to honest (conservative)",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
// Simulate the verification logic
isHonest := simulateWitnessPageCountVerification(tt.reportedPages, tt.peerPages)

if isHonest != tt.expectedHonest {
t.Errorf("%s: expected honest=%v, got honest=%v", tt.description, tt.expectedHonest, isHonest)
}
})
}
}

// simulateWitnessPageCountVerification simulates the verification logic from witness_manager.go
func simulateWitnessPageCountVerification(reportedPageCount uint64, peerPageCounts []uint64) bool {
const witnessPageWarningThreshold = 10
const witnessVerificationPeers = 2

// If under threshold, assume honest
if reportedPageCount <= witnessPageWarningThreshold {
return true
}

// If insufficient peers, assume honest (conservative approach)
if len(peerPageCounts) < witnessVerificationPeers {
return true
}

// Check for consensus among peers
consensusCount := uint64(0)
honestPeers := 0

for _, pageCount := range peerPageCounts {
honestPeers++
if consensusCount == 0 {
consensusCount = pageCount
} else if consensusCount != pageCount {
// No clear consensus
consensusCount = 0
break
}
}

// If we have consensus from at least 2 peers
if honestPeers >= witnessVerificationPeers && consensusCount > 0 {
return consensusCount == reportedPageCount
}

// No clear consensus, assume honest (conservative approach)
return true
}

// TestWitnessVerificationScenarios tests various verification scenarios
func TestWitnessVerificationScenarios(t *testing.T) {
t.Run("MaliciousPeer_ExcessivePages", func(t *testing.T) {
// Simulate a malicious peer reporting 1000+ pages
reportedPages := uint64(1000)
peerPages := []uint64{15, 15} // Other peers report normal page count

isHonest := simulateWitnessPageCountVerification(reportedPages, peerPages)

if isHonest {
t.Error("Expected malicious peer with excessive pages to be marked as dishonest")
}
})

t.Run("HonestPeer_LargeButReasonablePages", func(t *testing.T) {
// Simulate an honest peer with large but reasonable page count
reportedPages := uint64(50)
peerPages := []uint64{50, 50} // Other peers agree

isHonest := simulateWitnessPageCountVerification(reportedPages, peerPages)

if !isHonest {
t.Error("Expected honest peer with large but reasonable pages to be marked as honest")
}
})

t.Run("NetworkPartition_ConservativeApproach", func(t *testing.T) {
// Simulate network partition where only one peer responds
reportedPages := uint64(100)
peerPages := []uint64{100} // Only one peer responds

isHonest := simulateWitnessPageCountVerification(reportedPages, peerPages)

if !isHonest {
t.Error("Expected conservative approach to mark peer as honest when insufficient consensus")
}
})

t.Run("ConsensusThreshold_EdgeCase", func(t *testing.T) {
// Test exactly at the warning threshold
reportedPages := uint64(10)
peerPages := []uint64{10, 10}

isHonest := simulateWitnessPageCountVerification(reportedPages, peerPages)

if !isHonest {
t.Error("Expected peer at threshold to be marked as honest")
}
})
}

// TestWitnessVerificationPerformance tests the performance characteristics
func TestWitnessVerificationPerformance(t *testing.T) {
t.Run("LargeWitness_Verification", func(t *testing.T) {
// Test with a very large witness (1000+ pages)
reportedPages := uint64(1000)
peerPages := []uint64{1000, 1000}

start := time.Now()
isHonest := simulateWitnessPageCountVerification(reportedPages, peerPages)
duration := time.Since(start)

if !isHonest {
t.Error("Expected large witness with consensus to be marked as honest")
}

// Verification should be fast (under 1ms)
if duration > time.Millisecond {
t.Errorf("Verification took too long: %v", duration)
}
})
}
5 changes: 5 additions & 0 deletions eth/fetcher/block_fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -1331,3 +1331,8 @@ func (f *BlockFetcher) forgetBlock(hash common.Hash) {
f.wm.forget(hash)
}
}

// GetWitnessManager returns the witness manager for external access
func (f *BlockFetcher) GetWitnessManager() *witnessManager {
return f.wm
}
Loading
Loading