Skip to content

Commit 54abe92

Browse files
authored
Deduplicate partial and full GMessage validation logic (#1010)
* Deduplicate partial and full GMessage validation logic Prior to launch the partial message validation logic was copied from the core of GPBFT to work within the activation timescale leaving a technical debt behind. The work pays back that debt by unifying the two validation logics into one. It: * alters the core GPBFT validation logic to understand the notion of partial messages. * changes the basic validation logic to worth with and without partial information. * moves GPBFT basic types into their own Go file to reduce clutter in the core GPBFT implementation * enhances tests to exercise both partial+full and full message validation in tests. Fixes #826 * Update docs on GMessage to clarify signature paylaod signing * Incorporate the entire message in computing cache key for messages
1 parent e17b0d9 commit 54abe92

20 files changed

+809
-893
lines changed

cmd/f3/aider.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import (
1717
"github.com/filecoin-project/go-f3/internal/psutil"
1818
"github.com/filecoin-project/go-f3/manifest"
1919
"github.com/filecoin-project/go-f3/observer"
20-
"github.com/filecoin-project/go-f3/pmsg"
2120
"github.com/libp2p/go-libp2p"
2221
pubsub "github.com/libp2p/go-libp2p-pubsub"
2322
"github.com/libp2p/go-libp2p/p2p/net/connmgr"
@@ -230,7 +229,7 @@ func aid(c *cli.Context, f3Chatter *pubsub.Topic) error {
230229
}
231230
fmt.Printf("⚙️ Found %d distinct senders\n", len(senders))
232231

233-
msgEncoding, err := encoding.NewZSTD[*pmsg.PartialGMessage]()
232+
msgEncoding, err := encoding.NewZSTD[*gpbft.PartialGMessage]()
234233
if err != nil {
235234
return fmt.Errorf("failed to create zstd message encoding: %w", err)
236235
}

encoding_bench_test.go

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"github.com/filecoin-project/go-bitfield"
88
"github.com/filecoin-project/go-f3/gpbft"
99
"github.com/filecoin-project/go-f3/internal/encoding"
10-
"github.com/filecoin-project/go-f3/pmsg"
1110
"github.com/ipfs/go-cid"
1211
"github.com/multiformats/go-multihash"
1312
"github.com/stretchr/testify/require"
@@ -17,7 +16,7 @@ const seed = 1413
1716

1817
func BenchmarkCborEncoding(b *testing.B) {
1918
rng := rand.New(rand.NewSource(seed))
20-
encoder := encoding.NewCBOR[*pmsg.PartialGMessage]()
19+
encoder := encoding.NewCBOR[*gpbft.PartialGMessage]()
2120
msg := generateRandomPartialGMessage(b, rng)
2221

2322
b.ResetTimer()
@@ -33,7 +32,7 @@ func BenchmarkCborEncoding(b *testing.B) {
3332

3433
func BenchmarkCborDecoding(b *testing.B) {
3534
rng := rand.New(rand.NewSource(seed))
36-
encoder := encoding.NewCBOR[*pmsg.PartialGMessage]()
35+
encoder := encoding.NewCBOR[*gpbft.PartialGMessage]()
3736
msg := generateRandomPartialGMessage(b, rng)
3837
data, err := encoder.Encode(msg)
3938
require.NoError(b, err)
@@ -42,7 +41,7 @@ func BenchmarkCborDecoding(b *testing.B) {
4241
b.ReportAllocs()
4342
b.RunParallel(func(pb *testing.PB) {
4443
for pb.Next() {
45-
var got pmsg.PartialGMessage
44+
var got gpbft.PartialGMessage
4645
require.NoError(b, encoder.Decode(data, &got))
4746
requireEqualPartialMessages(b, msg, &got)
4847
}
@@ -51,7 +50,7 @@ func BenchmarkCborDecoding(b *testing.B) {
5150

5251
func BenchmarkZstdEncoding(b *testing.B) {
5352
rng := rand.New(rand.NewSource(seed))
54-
encoder, err := encoding.NewZSTD[*pmsg.PartialGMessage]()
53+
encoder, err := encoding.NewZSTD[*gpbft.PartialGMessage]()
5554
require.NoError(b, err)
5655
msg := generateRandomPartialGMessage(b, rng)
5756

@@ -68,7 +67,7 @@ func BenchmarkZstdEncoding(b *testing.B) {
6867

6968
func BenchmarkZstdDecoding(b *testing.B) {
7069
rng := rand.New(rand.NewSource(seed))
71-
encoder, err := encoding.NewZSTD[*pmsg.PartialGMessage]()
70+
encoder, err := encoding.NewZSTD[*gpbft.PartialGMessage]()
7271
require.NoError(b, err)
7372
msg := generateRandomPartialGMessage(b, rng)
7473
data, err := encoder.Encode(msg)
@@ -78,14 +77,14 @@ func BenchmarkZstdDecoding(b *testing.B) {
7877
b.ReportAllocs()
7978
b.RunParallel(func(pb *testing.PB) {
8079
for pb.Next() {
81-
var got pmsg.PartialGMessage
80+
var got gpbft.PartialGMessage
8281
require.NoError(b, encoder.Decode(data, &got))
8382
requireEqualPartialMessages(b, msg, &got)
8483
}
8584
})
8685
}
8786

88-
func requireEqualPartialMessages(b *testing.B, expected, actual *pmsg.PartialGMessage) {
87+
func requireEqualPartialMessages(b *testing.B, expected, actual *gpbft.PartialGMessage) {
8988
// Because empty ECChain gets marshaled as null, we need to use ECChain.Eq for
9089
// checking equality. Hence, the custom equality check.
9190
require.Equal(b, expected.Sender, actual.Sender)
@@ -103,8 +102,8 @@ func requireEqualPartialMessages(b *testing.B, expected, actual *pmsg.PartialGMe
103102
}
104103
}
105104

106-
func generateRandomPartialGMessage(b *testing.B, rng *rand.Rand) *pmsg.PartialGMessage {
107-
var pgmsg pmsg.PartialGMessage
105+
func generateRandomPartialGMessage(b *testing.B, rng *rand.Rand) *gpbft.PartialGMessage {
106+
var pgmsg gpbft.PartialGMessage
108107
pgmsg.GMessage = generateRandomGMessage(b, rng)
109108
pgmsg.GMessage.Vote.Value = nil
110109
if pgmsg.Justification != nil {

gen/main.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"github.com/filecoin-project/go-f3/certs"
99
"github.com/filecoin-project/go-f3/chainexchange"
1010
"github.com/filecoin-project/go-f3/gpbft"
11-
"github.com/filecoin-project/go-f3/pmsg"
1211
gen "github.com/whyrusleeping/cbor-gen"
1312
"golang.org/x/sync/errgroup"
1413
)
@@ -22,6 +21,7 @@ func main() {
2221
gpbft.TipSet{},
2322
gpbft.LegacyECChain{},
2423
gpbft.GMessage{},
24+
gpbft.PartialGMessage{},
2525
gpbft.SupplementalData{},
2626
gpbft.Payload{},
2727
gpbft.Justification{},
@@ -47,11 +47,6 @@ func main() {
4747
chainexchange.Message{},
4848
)
4949
})
50-
eg.Go(func() error {
51-
return gen.WriteTupleEncodersToFile("../pmsg/cbor_gen.go", "pmsg",
52-
pmsg.PartialGMessage{},
53-
)
54-
})
5550
if err := eg.Wait(); err != nil {
5651
fmt.Printf("Failed to complete cborg_gen: %v\n", err)
5752
os.Exit(1)

gpbft/api.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ type ValidatedMessage interface {
3131
Message() *GMessage
3232
}
3333

34+
type PartialMessageValidator interface {
35+
PartiallyValidateMessage(ctx context.Context, msg *PartialGMessage) (PartiallyValidatedMessage, error)
36+
FullyValidateMessage(ctx context.Context, msg PartiallyValidatedMessage) (ValidatedMessage, error)
37+
}
38+
39+
type PartiallyValidatedMessage interface {
40+
// Returns the partially validated message.
41+
PartialMessage() *PartialGMessage
42+
}
43+
3444
// Receives a Granite protocol message.
3545
// Calls to methods on this interface are expected to be serialized.
3646
// The methods are not safe for concurrent use, and may panic if called concurrently.

gpbft/cbor_gen.go

Lines changed: 100 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

gpbft/errors.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package gpbft
22

3-
import "errors"
3+
import (
4+
"errors"
5+
"fmt"
6+
"runtime/debug"
7+
)
48

59
var (
610
_ error = (*ValidationError)(nil)
@@ -40,5 +44,21 @@ var (
4044
// ValidationError signals that an error has occurred while validating a GMessage.
4145
type ValidationError struct{ message string }
4246

47+
type PanicError struct {
48+
Cause any
49+
stackTrace string
50+
}
51+
4352
func newValidationError(message string) ValidationError { return ValidationError{message: message} }
4453
func (e ValidationError) Error() string { return e.message }
54+
55+
func newPanicError(cause any) *PanicError {
56+
return &PanicError{
57+
Cause: cause,
58+
stackTrace: string(debug.Stack()),
59+
}
60+
}
61+
62+
func (e *PanicError) Error() string {
63+
return fmt.Sprintf("participant panicked: %v\n%v", e.Cause, e.stackTrace)
64+
}

0 commit comments

Comments
 (0)