diff --git a/chain/indexer/integrated/processor/state.go b/chain/indexer/integrated/processor/state.go index 626152bd..6726fbe3 100644 --- a/chain/indexer/integrated/processor/state.go +++ b/chain/indexer/integrated/processor/state.go @@ -804,7 +804,9 @@ func MakeProcessors(api tasks.DataSource, indexerTasks []string) (*IndexerProces out.TipsetProcessors[t] = drandtask.NewTask() case tasktype.ChainEconomics: - out.TipsetProcessors[t] = chainecontask.NewTask(api) + out.TipsetProcessors[t] = chainecontask.NewTask(api, 0) + case tasktype.ChainEconomicsV2: + out.TipsetProcessors[t] = chainecontask.NewTask(api, 2) case tasktype.ChainConsensus: out.TipsetProcessors[t] = consensustask.NewTask(api) diff --git a/chain/indexer/integrated/processor/state_internal_test.go b/chain/indexer/integrated/processor/state_internal_test.go index a45b5804..0db8f2ed 100644 --- a/chain/indexer/integrated/processor/state_internal_test.go +++ b/chain/indexer/integrated/processor/state_internal_test.go @@ -51,7 +51,7 @@ func TestNewProcessor(t *testing.T) { require.NoError(t, err) require.Equal(t, t.Name(), proc.name) require.Len(t, proc.actorProcessors, 26) - require.Len(t, proc.tipsetProcessors, 10) + require.Len(t, proc.tipsetProcessors, 11) require.Len(t, proc.tipsetsProcessors, 15) require.Len(t, proc.builtinProcessors, 1) @@ -70,7 +70,7 @@ func TestNewProcessor(t *testing.T) { require.Equal(t, headers.NewTask(), proc.tipsetProcessors[tasktype.BlockHeader]) require.Equal(t, parents.NewTask(), proc.tipsetProcessors[tasktype.BlockParent]) require.Equal(t, drand.NewTask(), proc.tipsetProcessors[tasktype.DrandBlockEntrie]) - require.Equal(t, chaineconomics.NewTask(nil), proc.tipsetProcessors[tasktype.ChainEconomics]) + require.Equal(t, chaineconomics.NewTask(nil, 0), proc.tipsetProcessors[tasktype.ChainEconomics]) require.Equal(t, consensus.NewTask(nil), proc.tipsetProcessors[tasktype.ChainConsensus]) require.Equal(t, gaseconomy.NewTask(nil), proc.tipsetProcessors[tasktype.MessageGasEconomy]) require.Equal(t, messageparam.NewTask(nil), proc.tipsetProcessors[tasktype.MessageParam]) diff --git a/chain/indexer/integrated/processor/state_test.go b/chain/indexer/integrated/processor/state_test.go index 5da5d196..f98871fd 100644 --- a/chain/indexer/integrated/processor/state_test.go +++ b/chain/indexer/integrated/processor/state_test.go @@ -384,7 +384,7 @@ func TestMakeProcessorsTipSet(t *testing.T) { require.Equal(t, headers.NewTask(), proc.TipsetProcessors[tasktype.BlockHeader]) require.Equal(t, parents.NewTask(), proc.TipsetProcessors[tasktype.BlockParent]) require.Equal(t, drand.NewTask(), proc.TipsetProcessors[tasktype.DrandBlockEntrie]) - require.Equal(t, chaineconomics.NewTask(nil), proc.TipsetProcessors[tasktype.ChainEconomics]) + require.Equal(t, chaineconomics.NewTask(nil, 0), proc.TipsetProcessors[tasktype.ChainEconomics]) require.Equal(t, consensus.NewTask(nil), proc.TipsetProcessors[tasktype.ChainConsensus]) require.Equal(t, gaseconomy.NewTask(nil), proc.TipsetProcessors[tasktype.MessageGasEconomy]) } @@ -443,7 +443,7 @@ func TestMakeProcessorsAllTasks(t *testing.T) { proc, err := processor.MakeProcessors(nil, append(tasktype.AllTableTasks, processor.BuiltinTaskName)) require.NoError(t, err) require.Len(t, proc.ActorProcessors, 26) - require.Len(t, proc.TipsetProcessors, 10) + require.Len(t, proc.TipsetProcessors, 11) require.Len(t, proc.TipsetsProcessors, 15) require.Len(t, proc.ReportProcessors, 1) } diff --git a/chain/indexer/tasktype/table_tasks.go b/chain/indexer/tasktype/table_tasks.go index f0d0d796..a715a3da 100644 --- a/chain/indexer/tasktype/table_tasks.go +++ b/chain/indexer/tasktype/table_tasks.go @@ -41,6 +41,7 @@ const ( IDAddress = "id_addresses" GasOutputs = "derived_gas_outputs" ChainEconomics = "chain_economics" + ChainEconomicsV2 = "chain_economics_v2" ChainConsensus = "chain_consensus" MultisigApproval = "multisig_approvals" VerifiedRegistryVerifier = "verified_registry_verifier" @@ -96,6 +97,7 @@ var AllTableTasks = []string{ IDAddress, GasOutputs, ChainEconomics, + ChainEconomicsV2, ChainConsensus, MultisigApproval, VerifiedRegistryVerifier, @@ -152,6 +154,7 @@ var TableLookup = map[string]struct{}{ IDAddress: {}, GasOutputs: {}, ChainEconomics: {}, + ChainEconomicsV2: {}, ChainConsensus: {}, MultisigApproval: {}, VerifiedRegistryVerifier: {}, @@ -208,6 +211,7 @@ var TableComment = map[string]string{ IDAddress: `IDAddress contains a mapping of ID addresses to robust addresses from the init actor’s state.`, GasOutputs: ``, ChainEconomics: ``, + ChainEconomicsV2: ``, ChainConsensus: ``, MultisigApproval: ``, VerifiedRegistryVerifier: ``, @@ -326,6 +330,7 @@ var TableFieldComments = map[string]map[string]string{ }, GasOutputs: {}, ChainEconomics: {}, + ChainEconomicsV2: {}, ChainConsensus: {}, MultisigApproval: {}, VerifiedRegistryVerifier: {}, diff --git a/chain/indexer/tasktype/tasks.go b/chain/indexer/tasktype/tasks.go index 4a76a363..5ffb9c03 100644 --- a/chain/indexer/tasktype/tasks.go +++ b/chain/indexer/tasktype/tasks.go @@ -83,6 +83,7 @@ var TaskLookup = map[string][]string{ }, ChainEconomicsTask: { ChainEconomics, + ChainEconomicsV2, }, MultisigApprovalsTask: { MultisigApproval, diff --git a/chain/indexer/tasktype/tasks_test.go b/chain/indexer/tasktype/tasks_test.go index 78f95245..280472ad 100644 --- a/chain/indexer/tasktype/tasks_test.go +++ b/chain/indexer/tasktype/tasks_test.go @@ -60,7 +60,7 @@ func TestMakeTaskNamesAlias(t *testing.T) { }, { taskAlias: tasktype.ChainEconomicsTask, - tasks: []string{tasktype.ChainEconomics}, + tasks: []string{tasktype.ChainEconomics, tasktype.ChainEconomicsV2}, }, { taskAlias: tasktype.MultisigApprovalsTask, @@ -102,7 +102,7 @@ func TestMakeAllTaskAliasNames(t *testing.T) { } func TestMakeAllTaskNames(t *testing.T) { - const TotalTableTasks = 53 + const TotalTableTasks = 54 actual, err := tasktype.MakeTaskNames(tasktype.AllTableTasks) require.NoError(t, err) // if this test fails it means a new task name was added, update the above test diff --git a/model/chain/economics.go b/model/chain/economics.go index c13559f9..33a8a42e 100644 --- a/model/chain/economics.go +++ b/model/chain/economics.go @@ -22,7 +22,6 @@ type ChainEconomics struct { BurntFil string `pg:"type:numeric,notnull"` LockedFil string `pg:"type:numeric,notnull"` FilReserveDisbursed string `pg:"type:numeric,notnull"` - LockedFilV2 string `pg:"type:numeric,notnull"` } type ChainEconomicsV0 struct { diff --git a/model/chain/economics_v2.go b/model/chain/economics_v2.go new file mode 100644 index 00000000..7971bb77 --- /dev/null +++ b/model/chain/economics_v2.go @@ -0,0 +1,49 @@ +package chain + +import ( + "context" + + "go.opencensus.io/tag" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + + "github.com/filecoin-project/lily/metrics" + "github.com/filecoin-project/lily/model" +) + +type ChainEconomicsV2 struct { + tableName struct{} `pg:"chain_economics_v2"` // nolint: structcheck + Height int64 `pg:",pk,notnull,use_zero"` + ParentStateRoot string `pg:",pk,notnull"` + CirculatingFilV2 string `pg:"type:numeric,notnull"` + VestedFil string `pg:"type:numeric,notnull"` + MinedFil string `pg:"type:numeric,notnull"` + BurntFil string `pg:"type:numeric,notnull"` + LockedFilV2 string `pg:"type:numeric,notnull"` + FilReserveDisbursed string `pg:"type:numeric,notnull"` +} + +func (c *ChainEconomicsV2) Persist(ctx context.Context, s model.StorageBatch, _ model.Version) error { + ctx, _ = tag.New(ctx, tag.Upsert(metrics.Table, "chain_economics")) + + metrics.RecordCount(ctx, metrics.PersistModel, 1) + return s.PersistModel(ctx, c) +} + +type ChainEconomicsV2List []*ChainEconomicsV2 + +func (l ChainEconomicsV2List) Persist(ctx context.Context, s model.StorageBatch, _ model.Version) error { + if len(l) == 0 { + return nil + } + ctx, span := otel.Tracer("").Start(ctx, "ChainEconomicsV2List.Persist") + if span.IsRecording() { + span.SetAttributes(attribute.Int("count", len(l))) + } + defer span.End() + + ctx, _ = tag.New(ctx, tag.Upsert(metrics.Table, "chain_economics_v2")) + + metrics.RecordCount(ctx, metrics.PersistModel, len(l)) + return s.PersistModel(ctx, l) +} diff --git a/schemas/v1/40_add_chaineconomics_v2.go b/schemas/v1/40_add_chaineconomics_v2.go new file mode 100644 index 00000000..d0b50d7b --- /dev/null +++ b/schemas/v1/40_add_chaineconomics_v2.go @@ -0,0 +1,24 @@ +package v1 + +func init() { + patches.Register( + 40, + ` + ALTER TABLE {{ .SchemaName | default "public"}}.chain_economics DROP COLUMN IF EXISTS locked_fil_v2; + + CREATE TABLE {{ .SchemaName | default "public"}}.chain_economics_v2 ( + height bigint NOT NULL, + parent_state_root text NOT NULL, + circulating_fil_v2 numeric NOT NULL, + vested_fil numeric NOT NULL, + mined_fil numeric NOT NULL, + burnt_fil numeric NOT NULL, + locked_fil_v2 numeric NOT NULL, + fil_reserve_disbursed numeric NOT NULL + ); + ALTER TABLE ONLY {{ .SchemaName | default "public"}}.chain_economics_v2 ADD CONSTRAINT chain_economics_v2_pk PRIMARY KEY (height, parent_state_root); + + CREATE INDEX IF NOT EXISTS chain_economics_v2_height_idx ON {{ .SchemaName | default "public"}}.chain_economics_v2 USING btree (height DESC); + `, + ) +} diff --git a/storage/sql.go b/storage/sql.go index 6f0823cb..ec8fbdcb 100644 --- a/storage/sql.go +++ b/storage/sql.go @@ -90,6 +90,7 @@ var Models = []interface{}{ (*derived.GasOutputs)(nil), (*chain.ChainEconomics)(nil), + (*chain.ChainEconomicsV2)(nil), (*chain.ChainConsensus)(nil), (*msapprovals.MultisigApproval)(nil), diff --git a/tasks/chaineconomics/economics.go b/tasks/chaineconomics/economics.go index 16cfce37..c85967be 100644 --- a/tasks/chaineconomics/economics.go +++ b/tasks/chaineconomics/economics.go @@ -9,7 +9,6 @@ import ( "go.opentelemetry.io/otel/attribute" "github.com/filecoin-project/go-address" - actorstypes "github.com/filecoin-project/go-state-types/actors" "github.com/filecoin-project/lily/chain/actors/adt" "github.com/filecoin-project/lily/chain/actors/builtin/miner" "github.com/filecoin-project/lily/model" @@ -54,16 +53,5 @@ func ExtractChainEconomicsModel(ctx context.Context, node ChainEconomicsLens, ts FilReserveDisbursed: supply.FilReserveDisbursed.String(), } - m, err := node.Actor(ctx, ts.MinTicketBlock().Miner, ts.Key()) - - if err != nil { - return chainEconomic, nil - } - - minerState, err := node.MinerLoad(node.Store(), m) - if err == nil && minerState.ActorVersion() >= actorstypes.Version14 { - chainEconomic.LockedFilV2 = supply.FilLocked.String() - } - return chainEconomic, nil } diff --git a/tasks/chaineconomics/economics_v2.go b/tasks/chaineconomics/economics_v2.go new file mode 100644 index 00000000..11e19d5f --- /dev/null +++ b/tasks/chaineconomics/economics_v2.go @@ -0,0 +1,48 @@ +package chaineconomics + +import ( + "context" + "fmt" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + + "github.com/filecoin-project/lily/lens/util" + chainmodel "github.com/filecoin-project/lily/model/chain" + + "github.com/filecoin-project/lotus/chain/types" + + network2 "github.com/filecoin-project/go-state-types/network" +) + +func ExtractChainEconomicsV2Model(ctx context.Context, node ChainEconomicsLens, ts *types.TipSet) (*chainmodel.ChainEconomicsV2, error) { + currentNetworkVersion := util.DefaultNetwork.Version(ctx, ts.Height()) + if currentNetworkVersion < network2.Version23 { + log.Infof("The chain_economics_v2 will be supported in nv23. Current network version is %v", currentNetworkVersion) + return nil, nil + } + + ctx, span := otel.Tracer("").Start(ctx, "ExtractChainEconomicsV2") + if span.IsRecording() { + span.SetAttributes(attribute.String("tipset", ts.String()), attribute.Int64("height", int64(ts.Height()))) + } + defer span.End() + + supply, err := node.CirculatingSupply(ctx, ts) + if err != nil { + return nil, fmt.Errorf("get circulating supply: %w", err) + } + + chainEconomicV2 := &chainmodel.ChainEconomicsV2{ + Height: int64(ts.Height()), + ParentStateRoot: ts.ParentState().String(), + VestedFil: supply.FilVested.String(), + MinedFil: supply.FilMined.String(), + BurntFil: supply.FilBurnt.String(), + LockedFilV2: supply.FilLocked.String(), + CirculatingFilV2: supply.FilCirculating.String(), + FilReserveDisbursed: supply.FilReserveDisbursed.String(), + } + + return chainEconomicV2, nil +} diff --git a/tasks/chaineconomics/task.go b/tasks/chaineconomics/task.go index bf5c17d0..ddfd08f9 100644 --- a/tasks/chaineconomics/task.go +++ b/tasks/chaineconomics/task.go @@ -7,6 +7,8 @@ import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" + network2 "github.com/filecoin-project/go-state-types/network" + "github.com/filecoin-project/lily/lens/util" "github.com/filecoin-project/lily/model" visormodel "github.com/filecoin-project/lily/model/visor" "github.com/filecoin-project/lily/tasks" @@ -17,12 +19,14 @@ import ( var log = logging.Logger("lily/tasks") type Task struct { - node tasks.DataSource + node tasks.DataSource + version int } -func NewTask(node tasks.DataSource) *Task { +func NewTask(node tasks.DataSource, version int) *Task { return &Task{ - node: node, + node: node, + version: version, } } @@ -40,6 +44,21 @@ func (p *Task) ProcessTipSet(ctx context.Context, ts *types.TipSet) (model.Persi StateRoot: ts.ParentState().String(), } + if p.version == 2 { + currentNetworkVersion := util.DefaultNetwork.Version(ctx, ts.Height()) + if currentNetworkVersion <= network2.Version23 { + log.Errorf("The chain_economics_v2 will be supported in nv23. Current network version is %v", currentNetworkVersion) + return nil, nil, nil + } + ce, err := ExtractChainEconomicsV2Model(ctx, p.node, ts) + if err != nil { + log.Errorw("error received while extracting chain economics, closing lens", "error", err) + return nil, nil, err + } + + return ce, report, nil + } + ce, err := ExtractChainEconomicsModel(ctx, p.node, ts) if err != nil { log.Errorw("error received while extracting chain economics, closing lens", "error", err)