Skip to content

Commit 4c51f28

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 4c51f28

File tree

3 files changed

+227
-58
lines changed

3 files changed

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

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)