Skip to content

Commit b55d6b9

Browse files
committed
fix: ensure all types referenced in the actors registry are CBOR marshallable
Ref: filecoin-project/go-state-types#397
1 parent 662f8e2 commit b55d6b9

File tree

3 files changed

+226
-58
lines changed

3 files changed

+226
-58
lines changed
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package builtin_test
2+
3+
import (
4+
"fmt"
5+
"reflect"
6+
"testing"
7+
8+
"github.com/stretchr/testify/require"
9+
10+
actorstypes "github.com/filecoin-project/go-state-types/actors"
11+
"github.com/filecoin-project/lotus/chain/actors"
12+
"github.com/filecoin-project/lotus/chain/actors/builtin"
13+
"github.com/filecoin-project/lotus/chain/vm"
14+
cbg "github.com/whyrusleeping/cbor-gen"
15+
)
16+
17+
// TestAllActorTypesCBORMarshaling checks that all types in the actor registry
18+
// implement the CBORMarshaler and CBORUnmarshaler interfaces
19+
func TestAllActorTypesCBORMarshaling(t *testing.T) {
20+
allTypesMissingCBOR := []string{}
21+
22+
for _, v := range actors.Versions {
23+
if v < 8 { // Skip versions before 8, as they's not referenced in the registry
24+
continue
25+
}
26+
av := actorstypes.Version(v)
27+
28+
t.Logf("\n=== Checking Actor Version %d ===", av)
29+
30+
// Create an ActorRegistry like the VM does
31+
ar := vm.NewActorRegistry()
32+
33+
// Register actors
34+
vmActors := builtin.MakeRegistry(av)
35+
ar.Register(av, nil, vmActors)
36+
37+
// Get actor code IDs for naming
38+
codeIDs, err := actors.GetActorCodeIDs(av)
39+
require.NoError(t, err, "Failed to get code IDs for version %d", av)
40+
41+
// Create reverse mapping from code ID to actor name
42+
codeToName := make(map[string]string)
43+
for name, codeID := range codeIDs {
44+
codeToName[codeID.String()] = name
45+
}
46+
47+
// Track statistics for this version
48+
totalChecked := 0
49+
typesMissingCBOR := []string{}
50+
51+
// Check each actor's methods
52+
for codeID, methods := range ar.Methods {
53+
actorName := codeToName[codeID.String()]
54+
if actorName == "" {
55+
actorName = fmt.Sprintf("Unknown(%s)", codeID)
56+
}
57+
58+
for methodNum, methodMeta := range methods {
59+
// Check params type
60+
if methodMeta.Params != nil && methodMeta.Params.Kind() != reflect.Invalid {
61+
totalChecked++
62+
if !implementsCBORInterfaces(methodMeta.Params) {
63+
msg := fmt.Sprintf("v%d %s Method %d (%s) - Params type %s",
64+
av, actorName, methodNum, methodMeta.Name, methodMeta.Params)
65+
typesMissingCBOR = append(typesMissingCBOR, msg)
66+
allTypesMissingCBOR = append(allTypesMissingCBOR, msg)
67+
}
68+
}
69+
70+
// Check return type
71+
if methodMeta.Ret != nil && methodMeta.Ret.Kind() != reflect.Invalid {
72+
totalChecked++
73+
if !implementsCBORInterfaces(methodMeta.Ret) {
74+
msg := fmt.Sprintf("v%d %s Method %d (%s) - Return type %s",
75+
av, actorName, methodNum, methodMeta.Name, methodMeta.Ret)
76+
typesMissingCBOR = append(typesMissingCBOR, msg)
77+
allTypesMissingCBOR = append(allTypesMissingCBOR, msg)
78+
}
79+
}
80+
}
81+
}
82+
83+
// Also check state types from the registry
84+
for _, entry := range vmActors {
85+
codeStr := entry.Code().String()
86+
actorName := codeToName[codeStr]
87+
if actorName == "" {
88+
actorName = fmt.Sprintf("Unknown(%s)", entry.Code())
89+
}
90+
91+
if entry.State() != nil {
92+
totalChecked++
93+
stateType := reflect.TypeOf(entry.State())
94+
if !implementsCBORInterfaces(stateType) {
95+
msg := fmt.Sprintf("v%d %s - State type %s",
96+
av, actorName, stateType)
97+
typesMissingCBOR = append(typesMissingCBOR, msg)
98+
allTypesMissingCBOR = append(allTypesMissingCBOR, msg)
99+
}
100+
}
101+
}
102+
103+
t.Logf("Version %d: Checked %d types, %d missing CBOR marshaling",
104+
av, totalChecked, len(typesMissingCBOR))
105+
106+
if len(typesMissingCBOR) > 0 {
107+
t.Logf("Types missing CBOR in v%d:", av)
108+
for _, typeInfo := range typesMissingCBOR {
109+
t.Logf(" ❌ %s", typeInfo)
110+
}
111+
}
112+
}
113+
114+
t.Logf("\n=== FINAL SUMMARY ===")
115+
t.Logf("Total types missing CBOR marshaling across all versions: %d", len(allTypesMissingCBOR))
116+
117+
if len(allTypesMissingCBOR) > 0 {
118+
// Print unique types for easier analysis
119+
uniqueTypes := make(map[string]bool)
120+
for _, msg := range allTypesMissingCBOR {
121+
uniqueTypes[msg] = true
122+
}
123+
124+
t.Logf("\nUnique types missing CBOR marshaling:")
125+
for typeInfo := range uniqueTypes {
126+
t.Logf(" - %s", typeInfo)
127+
}
128+
129+
// This test is expected to fail currently
130+
require.Failf(t, "CBOR marshaling missing", "Found %d types that do not implement CBORMarshaler/CBORUnmarshaler interfaces", len(uniqueTypes))
131+
}
132+
}
133+
134+
// implementsCBORInterfaces checks if a reflect.Type implements both CBORMarshaler and CBORUnmarshaler
135+
func implementsCBORInterfaces(t reflect.Type) bool {
136+
if t == nil || t.Kind() == reflect.Invalid {
137+
return true // nil/invalid is considered "implementing" for our purposes
138+
}
139+
140+
// Get interface types
141+
marshalerType := reflect.TypeOf((*cbg.CBORMarshaler)(nil)).Elem()
142+
unmarshalerType := reflect.TypeOf((*cbg.CBORUnmarshaler)(nil)).Elem()
143+
144+
// For interface types, we can't check implementation
145+
if t.Kind() == reflect.Interface {
146+
return true // assume interfaces are OK
147+
}
148+
149+
// Check if either the type or pointer to type implements both interfaces
150+
implementsAsValue := t.Implements(marshalerType) && t.Implements(unmarshalerType)
151+
152+
// For non-pointer types, also check if pointer to type implements
153+
if t.Kind() != reflect.Ptr && t.Kind() != reflect.Interface {
154+
ptrType := reflect.PointerTo(t)
155+
implementsAsPointer := ptrType.Implements(marshalerType) && ptrType.Implements(unmarshalerType)
156+
return implementsAsValue || implementsAsPointer
157+
}
158+
159+
return implementsAsValue
160+
}

go.mod

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ require (
5151
github.com/filecoin-project/go-jsonrpc v0.7.0
5252
github.com/filecoin-project/go-padreader v0.0.1
5353
github.com/filecoin-project/go-paramfetch v0.0.4
54-
github.com/filecoin-project/go-state-types v0.17.0-dev2 // dependency-check-ignore: unknown
54+
github.com/filecoin-project/go-state-types v0.17.0-dev2.0.20250704112250-b7cbcb227e0b // dependency-check-ignore: unknown
5555
github.com/filecoin-project/go-statemachine v1.0.3
5656
github.com/filecoin-project/go-statestore v0.2.0
5757
github.com/filecoin-project/go-storedcounter v0.1.0
@@ -85,21 +85,21 @@ require (
8585
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab
8686
github.com/invopop/jsonschema v0.12.0
8787
github.com/ipfs/bbloom v0.0.4
88-
github.com/ipfs/boxo v0.20.0
89-
github.com/ipfs/go-block-format v0.2.0
88+
github.com/ipfs/boxo v0.32.0
89+
github.com/ipfs/go-block-format v0.2.2
9090
github.com/ipfs/go-cid v0.5.0
9191
github.com/ipfs/go-datastore v0.8.2
9292
github.com/ipfs/go-ds-badger2 v0.1.5
9393
github.com/ipfs/go-ds-leveldb v0.5.0
9494
github.com/ipfs/go-ds-measure v0.2.0
9595
github.com/ipfs/go-fs-lock v0.0.7
96-
github.com/ipfs/go-ipld-cbor v0.2.0
97-
github.com/ipfs/go-ipld-format v0.6.0
96+
github.com/ipfs/go-ipld-cbor v0.2.1
97+
github.com/ipfs/go-ipld-format v0.6.2
9898
github.com/ipfs/go-log/v2 v2.6.0
99-
github.com/ipfs/go-metrics-interface v0.0.1
99+
github.com/ipfs/go-metrics-interface v0.3.0
100100
github.com/ipfs/go-metrics-prometheus v0.0.2
101101
github.com/ipld/go-car v0.6.2
102-
github.com/ipld/go-car/v2 v2.13.1
102+
github.com/ipld/go-car/v2 v2.14.3
103103
github.com/ipld/go-ipld-prime v0.21.0
104104
github.com/jackc/pgerrcode v0.0.0-20240316143900-6e2875d9b438
105105
github.com/jpillora/backoff v1.0.0
@@ -108,10 +108,10 @@ require (
108108
github.com/koalacxr/quantile v0.0.1
109109
github.com/libp2p/go-buffer-pool v0.1.0
110110
github.com/libp2p/go-libp2p v0.42.0
111-
github.com/libp2p/go-libp2p-kad-dht v0.25.2
111+
github.com/libp2p/go-libp2p-kad-dht v0.33.1
112112
github.com/libp2p/go-libp2p-pubsub v0.13.0
113-
github.com/libp2p/go-libp2p-record v0.2.0
114-
github.com/libp2p/go-libp2p-routing-helpers v0.7.3
113+
github.com/libp2p/go-libp2p-record v0.3.1
114+
github.com/libp2p/go-libp2p-routing-helpers v0.7.5
115115
github.com/libp2p/go-maddr-filter v0.1.0
116116
github.com/libp2p/go-msgio v0.3.0
117117
github.com/manifoldco/promptui v0.9.0
@@ -130,7 +130,7 @@ require (
130130
github.com/puzpuzpuz/xsync/v2 v2.4.0
131131
github.com/raulk/clock v1.1.0
132132
github.com/raulk/go-watchdog v1.3.0
133-
github.com/samber/lo v1.39.0
133+
github.com/samber/lo v1.47.0
134134
github.com/sirupsen/logrus v1.9.2
135135
github.com/stretchr/testify v1.10.0
136136
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // dependency-check-ignore: unknown
@@ -145,11 +145,11 @@ require (
145145
github.com/zondax/ledger-filecoin-go v1.0.1
146146
github.com/zyedidia/generic v1.2.1
147147
go.opencensus.io v0.24.0
148-
go.opentelemetry.io/otel v1.34.0
148+
go.opentelemetry.io/otel v1.35.0
149149
go.opentelemetry.io/otel/bridge/opencensus v1.28.0
150150
go.opentelemetry.io/otel/exporters/jaeger v1.14.0
151151
go.opentelemetry.io/otel/exporters/prometheus v0.50.0
152-
go.opentelemetry.io/otel/metric v1.34.0
152+
go.opentelemetry.io/otel/metric v1.35.0
153153
go.opentelemetry.io/otel/sdk v1.34.0
154154
go.opentelemetry.io/otel/sdk/metric v1.32.0
155155
go.uber.org/fx v1.24.0
@@ -240,16 +240,15 @@ require (
240240
github.com/ipfs/go-ipld-legacy v0.2.1 // indirect
241241
github.com/ipfs/go-log v1.0.5 // indirect
242242
github.com/ipfs/go-merkledag v0.11.0 // indirect
243-
github.com/ipfs/go-peertaskqueue v0.8.1 // indirect
243+
github.com/ipfs/go-peertaskqueue v0.8.2 // indirect
244244
github.com/ipfs/go-verifcid v0.0.3 // indirect
245-
github.com/ipld/go-codec-dagpb v1.6.0 // indirect
245+
github.com/ipld/go-codec-dagpb v1.7.0 // indirect
246246
github.com/jackc/pgpassfile v1.0.0 // indirect
247247
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect
248248
github.com/jackc/pgx/v5 v5.6.0 // indirect
249249
github.com/jackc/puddle/v2 v2.2.1 // indirect
250250
github.com/jackpal/go-nat-pmp v1.0.2 // indirect
251251
github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
252-
github.com/jbenet/goprocess v0.1.4 // indirect
253252
github.com/jessevdk/go-flags v1.4.0 // indirect
254253
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 // indirect
255254
github.com/josharian/intern v1.0.0 // indirect
@@ -259,7 +258,7 @@ require (
259258
github.com/libp2p/go-cidranger v1.1.0 // indirect
260259
github.com/libp2p/go-flow-metrics v0.2.0 // indirect
261260
github.com/libp2p/go-libp2p-asn-util v0.4.1 // indirect
262-
github.com/libp2p/go-libp2p-kbucket v0.6.3 // indirect
261+
github.com/libp2p/go-libp2p-kbucket v0.7.0 // indirect
263262
github.com/libp2p/go-netroute v0.2.2 // indirect
264263
github.com/libp2p/go-reuseport v0.4.0 // indirect
265264
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
@@ -332,14 +331,14 @@ require (
332331
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect
333332
go.dedis.ch/fixbuf v1.0.3 // indirect
334333
go.dedis.ch/kyber/v4 v4.0.0-pre2.0.20240924132404-4de33740016e // indirect; dependency-check-ignore: unknown
335-
go.opentelemetry.io/otel/trace v1.34.0 // indirect
334+
go.opentelemetry.io/otel/trace v1.35.0 // indirect
336335
go.uber.org/atomic v1.11.0 // indirect
337336
go.uber.org/dig v1.19.0 // indirect
338337
go.uber.org/mock v0.5.2 // indirect
339338
go4.org v0.0.0-20230225012048-214862532bf5 // indirect
340339
golang.org/x/exp v0.0.0-20250606033433-dcc06ee1d476 // indirect
341340
golang.org/x/text v0.26.0 // indirect
342-
gonum.org/v1/gonum v0.15.0 // indirect
341+
gonum.org/v1/gonum v0.16.0 // indirect
343342
google.golang.org/genproto/googleapis/api v0.0.0-20250212204824-5a70512c5d8b // indirect
344343
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b // indirect
345344
google.golang.org/grpc v1.70.0 // indirect
@@ -353,6 +352,8 @@ require (
353352
)
354353

355354
require (
355+
github.com/gammazero/chanqueue v1.1.0 // indirect
356+
github.com/gammazero/deque v1.0.0 // indirect
356357
github.com/libp2p/go-yamux/v5 v5.0.1 // indirect
357358
github.com/pion/dtls/v3 v3.0.6 // indirect
358359
github.com/pion/ice/v4 v4.0.10 // indirect

0 commit comments

Comments
 (0)