Skip to content

Commit e03bdb0

Browse files
authored
Test bad justification (#332)
- Invalid bitfield - Participant without power
1 parent d1b048a commit e03bdb0

File tree

2 files changed

+94
-10
lines changed

2 files changed

+94
-10
lines changed

sim/adversary/decide.go

+48-10
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,39 @@ import (
1010

1111
var _ Receiver = (*ImmediateDecide)(nil)
1212

13+
type ImmediateDecideOption func(*ImmediateDecide)
14+
15+
func ImmediateDecideWithNthParticipant(n uint64) ImmediateDecideOption {
16+
return func(i *ImmediateDecide) {
17+
i.additionalParticipant = &n
18+
}
19+
}
20+
1321
// / An "adversary" that immediately sends a DECIDE message, justified by its own COMMIT.
1422
type ImmediateDecide struct {
1523
id gpbft.ActorID
1624
host Host
1725
value gpbft.ECChain
26+
27+
additionalParticipant *uint64
1828
}
1929

20-
func NewImmediateDecide(id gpbft.ActorID, host Host, value gpbft.ECChain) *ImmediateDecide {
21-
return &ImmediateDecide{
30+
func NewImmediateDecide(id gpbft.ActorID, host Host, value gpbft.ECChain, opts ...ImmediateDecideOption) *ImmediateDecide {
31+
i := &ImmediateDecide{
2232
id: id,
2333
host: host,
2434
value: value,
2535
}
36+
for _, opt := range opts {
37+
opt(i)
38+
}
39+
return i
2640
}
2741

28-
func NewImmediateDecideGenerator(value gpbft.ECChain, power *gpbft.StoragePower) Generator {
42+
func NewImmediateDecideGenerator(value gpbft.ECChain, power *gpbft.StoragePower, opts ...ImmediateDecideOption) Generator {
2943
return func(id gpbft.ActorID, host Host) *Adversary {
3044
return &Adversary{
31-
Receiver: NewImmediateDecide(id, host, value),
45+
Receiver: NewImmediateDecide(id, host, value, opts...),
3246
Power: power,
3347
}
3448
}
@@ -55,15 +69,39 @@ func (i *ImmediateDecide) StartInstanceAt(instance uint64, _when time.Time) erro
5569
SupplementalData: *supplementalData,
5670
}
5771
sigPayload := i.host.MarshalPayloadForSigning(i.host.NetworkName(), &justificationPayload)
58-
_, pubkey := powertable.Get(i.id)
59-
sig, err := i.host.Sign(context.Background(), pubkey, sigPayload)
60-
if err != nil {
72+
signers := bitfield.New()
73+
74+
signers.Set(uint64(powertable.Lookup[i.id]))
75+
76+
if i.additionalParticipant != nil {
77+
signers.Set(*i.additionalParticipant)
78+
}
79+
80+
var (
81+
pubkeys []gpbft.PubKey
82+
sigs [][]byte
83+
)
84+
85+
if err := signers.ForEach(func(j uint64) error {
86+
pubkey := gpbft.PubKey("fake pubkey")
87+
sig := []byte("fake sig")
88+
if j < uint64(len(powertable.Entries)) {
89+
pubkey = powertable.Entries[j].PubKey
90+
var err error
91+
sig, err = i.host.Sign(context.Background(), pubkey, sigPayload)
92+
if err != nil {
93+
return err
94+
}
95+
}
96+
97+
pubkeys = append(pubkeys, pubkey)
98+
sigs = append(sigs, sig)
99+
return nil
100+
}); err != nil {
61101
panic(err)
62102
}
63103

64-
signers := bitfield.New()
65-
signers.Set(uint64(powertable.Lookup[i.id]))
66-
aggregatedSig, err := i.host.Aggregate([]gpbft.PubKey{pubkey}, [][]byte{sig})
104+
aggregatedSig, err := i.host.Aggregate(pubkeys, sigs)
67105
if err != nil {
68106
panic(err)
69107
}

test/decide_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,49 @@ func FuzzImmediateDecideAdversary(f *testing.F) {
4747
require.Equal(t, adversaryValue.Head(), decision.Head(), "honest node did not decide the right value")
4848
})
4949
}
50+
51+
func TestIllegalCommittee_OutOfRange(t *testing.T) {
52+
const seed = 98562314
53+
t.Parallel()
54+
rng := rand.New(rand.NewSource(int64(seed)))
55+
tsg := sim.NewTipSetGenerator(tipSetGeneratorSeed)
56+
baseChain := generateECChain(t, tsg)
57+
adversaryValue := baseChain.Extend(tsg.Sample())
58+
sm, err := sim.NewSimulation(
59+
asyncOptions(rng.Int(),
60+
sim.AddHonestParticipants(
61+
1,
62+
sim.NewUniformECChainGenerator(rng.Uint64(), 1, 5),
63+
uniformOneStoragePower),
64+
sim.WithBaseChain(&baseChain),
65+
// Add the adversary to the simulation with 3/4 of total power.
66+
sim.WithAdversary(adversary.NewImmediateDecideGenerator(adversaryValue, gpbft.NewStoragePower(3), adversary.ImmediateDecideWithNthParticipant(100))),
67+
)...)
68+
require.NoError(t, err)
69+
70+
err = sm.Run(1, maxRounds)
71+
require.ErrorContains(t, err, "invalid signer index")
72+
}
73+
74+
func TestIllegalCommittee_NoPower(t *testing.T) {
75+
const seed = 98562314
76+
t.Parallel()
77+
rng := rand.New(rand.NewSource(int64(seed)))
78+
tsg := sim.NewTipSetGenerator(tipSetGeneratorSeed)
79+
baseChain := generateECChain(t, tsg)
80+
adversaryValue := baseChain.Extend(tsg.Sample())
81+
sm, err := sim.NewSimulation(
82+
asyncOptions(rng.Int(),
83+
sim.AddHonestParticipants(
84+
1,
85+
sim.NewUniformECChainGenerator(rng.Uint64(), 1, 5),
86+
sim.UniformStoragePower(gpbft.NewStoragePower(1))),
87+
sim.WithBaseChain(&baseChain),
88+
// Add the adversary to the simulation with 3/4 of total power.
89+
sim.WithAdversary(adversary.NewImmediateDecideGenerator(adversaryValue, gpbft.NewStoragePower(0xffff), adversary.ImmediateDecideWithNthParticipant(1))),
90+
)...)
91+
require.NoError(t, err)
92+
93+
err = sm.Run(1, maxRounds)
94+
require.ErrorContains(t, err, "signer with ID 0 has no power")
95+
}

0 commit comments

Comments
 (0)