Skip to content

Commit 0e3a578

Browse files
committed
feat(api): make initial /v2/ API actually work
1 parent f184c1d commit 0e3a578

24 files changed

+612
-116
lines changed

api/v2api/full.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55

66
"github.com/filecoin-project/go-jsonrpc"
7+
"github.com/filecoin-project/go-state-types/abi"
78

89
"github.com/filecoin-project/lotus/api"
910
"github.com/filecoin-project/lotus/chain/types"
@@ -34,29 +35,27 @@ type FullNode interface {
3435
// ChainGetMessagesInTipset returns message stores in current tipset. Takes
3536
// a TipSetKey or an EpochSelector (either "latest" or "finalized") as an
3637
// argument.
37-
ChainGetMessagesInTipset(ctx context.Context, tskes types.TipSetKeyOrEpochSelector) ([]api.Message, error) //perm:read
38+
ChainGetMessagesInTipset(ctx context.Context, tss types.TipSetSelector) ([]api.Message, error) //perm:read
3839

3940
// ChainGetTipSetByHeight looks back for a tipset at at the specified epoch
40-
// or epoch selector (either "latest" or "finalized") and returns the tipset
41-
// at that epoch.
41+
// and returns the tipset at that epoch.
4242
// If there are no blocks at the specified epoch because it was a null
4343
// round, a tipset at an earlier epoch will be returned.
4444
// The second argument is an optional TipSetKey or EpochSelector (either
4545
// "latest" or "finalized") to specify the point in the chain to begin
4646
// looking for the tipset.
47-
ChainGetTipSetByHeight(ctx context.Context, hes types.HeightOrEpochSelector, tskes types.TipSetKeyOrEpochSelector) (*types.TipSet, error) //perm:read
47+
ChainGetTipSetByHeight(ctx context.Context, epoch abi.ChainEpoch, tss types.TipSetSelector) (*types.TipSet, error) //perm:read
4848

4949
// ChainGetTipSetAfterHeight looks back for a tipset at the specified epoch
50-
// or epoch selector (either "latest" or "finalized") and returns the tipset
51-
// at that epoch.
50+
// and returns the tipset at that epoch.
5251
// If there are no blocks at the specified epoch because it was a null
5352
// round, a tipset at a later epoch will be returned.
5453
// The second argument is an optional TipSetKey or EpochSelector (either
5554
// "latest" or "finalized") to specify the point in the chain to begin
5655
// looking for the tipset.
57-
ChainGetTipSetAfterHeight(ctx context.Context, hes types.HeightOrEpochSelector, tskes types.TipSetKeyOrEpochSelector) (*types.TipSet, error) //perm:read
56+
ChainGetTipSetAfterHeight(ctx context.Context, epoch abi.ChainEpoch, tss types.TipSetSelector) (*types.TipSet, error) //perm:read
5857

59-
// TODO: consider these for tsk argument extension using TipSetKeyOrEpochSelector
58+
// TODO: consider these for tsk argument extension using TipSetSelector
6059
//
6160
// ChainTipSetWeight
6261
// ChainGetPath -- from [foo,bar] to "latest" would be neat, or from "finalized" to "latest"

api/v2api/permissioned.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package v2api
2+
3+
import (
4+
"github.com/filecoin-project/go-jsonrpc/auth"
5+
6+
"github.com/filecoin-project/lotus/api"
7+
)
8+
9+
func PermissionedFullAPI(a FullNode) FullNode {
10+
var out FullNodeStruct
11+
auth.PermissionedProxy(api.AllPermissions, api.DefaultPerms, a, &out.Internal)
12+
return &out
13+
}

api/v2api/proxy_gen.go

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

api/v2api/v2mocks/mock_full.go

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

chain/lf3/f3.go

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package lf3
33
import (
44
"context"
55
"errors"
6+
"fmt"
67
"path/filepath"
78

89
"github.com/ipfs/go-datastore"
@@ -18,9 +19,11 @@ import (
1819
"github.com/filecoin-project/go-f3/certs"
1920
"github.com/filecoin-project/go-f3/gpbft"
2021
"github.com/filecoin-project/go-f3/manifest"
22+
"github.com/filecoin-project/go-state-types/abi"
2123

2224
"github.com/filecoin-project/lotus/api"
2325
"github.com/filecoin-project/lotus/chain"
26+
"github.com/filecoin-project/lotus/chain/actors/policy"
2427
"github.com/filecoin-project/lotus/chain/stmgr"
2528
"github.com/filecoin-project/lotus/chain/store"
2629
"github.com/filecoin-project/lotus/chain/types"
@@ -82,6 +85,7 @@ func New(mctx helpers.MetricsCtx, lc fx.Lifecycle, params F3Params) (*F3, error)
8285
status := func() (*manifest.Manifest, gpbft.Instant) {
8386
return module.Manifest(), module.Progress()
8487
}
88+
8589
fff := &F3{
8690
inner: module,
8791
ec: ec,
@@ -228,3 +232,143 @@ func (fff *F3) ListParticipants() []api.F3Participant {
228232
}
229233
return participants
230234
}
235+
236+
// ResolveTipSetKeySelector resolves a TipSetSelector into a concrete TipSetKey.
237+
//
238+
// For TipSetKey selectors, returns the key directly.
239+
// For epoch descriptors:
240+
// - "latest" returns the current heaviest tipset
241+
// - "finalized" returns the most recently finalized tipset, using either F3
242+
// or EC finality depending on whether F3 is enabled and running.
243+
//
244+
// Returns:
245+
// - TipSetKey: The resolved tipset key (this may be EmptyTSK if that was
246+
// the selector)
247+
// - error: On invalid selectors or resolution failures
248+
func ResolveTipSetKeySelector(ctx context.Context, fff *F3, chain *store.ChainStore, tss types.TipSetSelector) (types.TipSetKey, error) {
249+
if tss.TipSetKey != nil {
250+
return *tss.TipSetKey, nil
251+
}
252+
if tss.EpochDescriptor == nil {
253+
return types.EmptyTSK, errors.New("invalid tipset selector")
254+
}
255+
switch *tss.EpochDescriptor {
256+
case types.EpochLatest:
257+
return chain.GetHeaviestTipSet().Key(), nil
258+
case types.EpochFinalized:
259+
if fff != nil { // F3 is enabled
260+
cert, err := fff.inner.GetLatestCert(ctx)
261+
if err == nil { // F3 is running
262+
tsk, err := types.TipSetKeyFromBytes(cert.ECChain.Head().Key)
263+
if err != nil {
264+
return types.EmptyTSK, xerrors.Errorf("decoding tipset key reported by F3: %w", err)
265+
}
266+
return tsk, nil
267+
}
268+
}
269+
// either F3 isn't enabled, or isn't running
270+
head := chain.GetHeaviestTipSet()
271+
finalizedHeight := head.Height() - policy.ChainFinality
272+
ts, err := chain.GetTipsetByHeight(ctx, finalizedHeight, head, true)
273+
if err != nil {
274+
return types.EmptyTSK, xerrors.Errorf("getting tipset by height: %w", err)
275+
}
276+
return ts.Key(), nil
277+
}
278+
return types.EmptyTSK, fmt.Errorf("invalid epoch descriptor: %s", *tss.EpochDescriptor)
279+
}
280+
281+
// ResolveTipSetSelector resolves a TipSetSelector into a concrete TipSet.
282+
//
283+
// For TipSetKey selectors, loads the tipset directly.
284+
// For epoch descriptors:
285+
// - "latest" returns the current heaviest tipset
286+
// - "finalized" returns the most recently finalized tipset, using either F3
287+
// or EC finality depending on whether F3 is enabled and running.
288+
//
289+
// Returns:
290+
// - TipSet: The resolved tipset
291+
// - error: On invalid selectors or resolution failures
292+
func ResolveTipSetSelector(ctx context.Context, fff *F3, chain *store.ChainStore, tss types.TipSetSelector) (*types.TipSet, error) {
293+
if tss.TipSetKey != nil {
294+
ts, err := chain.GetTipSetFromKey(ctx, *tss.TipSetKey)
295+
if err != nil {
296+
return nil, xerrors.Errorf("loading tipset %s: %w", *tss.TipSetKey, err)
297+
}
298+
return ts, nil
299+
}
300+
if tss.EpochDescriptor == nil {
301+
return nil, errors.New("invalid tipset selector")
302+
}
303+
304+
return ResolveEpochDescriptorTipSet(ctx, fff, chain, *tss.EpochDescriptor)
305+
}
306+
307+
// ResolveEpochSelector resolves an EpochSelector into a concrete ChainEpoch.
308+
//
309+
// For ChainEpoch selectors, returns the epoch directly.
310+
// For epoch descriptors:
311+
// - "latest" returns the current epoch
312+
// - "finalized" returns the most recently finalized epoch, using either F3
313+
// or EC finality depending on whether F3 is enabled and running.
314+
//
315+
// Returns:
316+
// - ChainEpoch: The resolved epoch
317+
// - error: On invalid selectors or resolution failures
318+
func ResolveEpochSelector(ctx context.Context, fff *F3, chain *store.ChainStore, es types.EpochSelector) (abi.ChainEpoch, error) {
319+
if es.ChainEpoch != nil {
320+
return *es.ChainEpoch, nil
321+
} else if es.EpochDescriptor == nil {
322+
return 0, errors.New("invalid epoch selector")
323+
}
324+
325+
if ts, err := ResolveEpochDescriptorTipSet(ctx, fff, chain, *es.EpochDescriptor); err != nil {
326+
return 0, xerrors.Errorf("resolving epoch descriptor: %w", err)
327+
} else {
328+
return ts.Height(), nil
329+
}
330+
}
331+
332+
// ResolveEpochDescriptorTipSet resolves an EpochDescriptor into a concrete TipSet.
333+
//
334+
// For "latest", returns the current heaviest tipset.
335+
// For "finalized", returns the most recently finalized tipset, using either F3
336+
// or EC finality depending on whether F3 is enabled and running.
337+
//
338+
// Returns:
339+
// - TipSet: The resolved tipset
340+
// - error: On invalid descriptors or resolution failures
341+
func ResolveEpochDescriptorTipSet(ctx context.Context, fff *F3, chain *store.ChainStore, ed types.EpochDescriptor) (*types.TipSet, error) {
342+
switch ed {
343+
case types.EpochLatest:
344+
return chain.GetHeaviestTipSet(), nil
345+
346+
case types.EpochFinalized:
347+
if fff != nil { // F3 is enabled
348+
cert, err := fff.inner.GetLatestCert(ctx)
349+
if err == nil { // F3 is running
350+
tsk, err := types.TipSetKeyFromBytes(cert.ECChain.Head().Key)
351+
if err != nil {
352+
return nil, xerrors.Errorf("decoding tipset key reported by F3: %w", err)
353+
}
354+
if ts, err := chain.LoadTipSet(ctx, tsk); err != nil {
355+
return nil, xerrors.Errorf("loading tipset %s: %w", tsk, err)
356+
} else {
357+
return ts, nil
358+
}
359+
}
360+
}
361+
362+
// either F3 isn't enabled, or isn't running
363+
head := chain.GetHeaviestTipSet()
364+
finalizedHeight := head.Height() - policy.ChainFinality
365+
if ts, err := chain.GetTipsetByHeight(ctx, finalizedHeight, head, true); err != nil {
366+
return nil, xerrors.Errorf("getting tipset by height: %w", err)
367+
} else {
368+
return ts, nil
369+
}
370+
371+
default:
372+
return nil, fmt.Errorf("invalid epoch descriptor: %s", ed)
373+
}
374+
}

0 commit comments

Comments
 (0)