diff --git a/model/actors/datacap/state.go b/model/actors/datacap/state.go index ce76d34b..91d4aed6 100644 --- a/model/actors/datacap/state.go +++ b/model/actors/datacap/state.go @@ -10,9 +10,11 @@ import ( ) const ( - Added = "ADDED" - Removed = "REMOVED" - Modified = "MODIFIED" + Added = "ADDED" + Removed = "REMOVED" + Modified = "MODIFIED" + Verifier = "verifier" + VerifierClient = "verifier_client" ) type DataCapBalance struct { @@ -20,8 +22,9 @@ type DataCapBalance struct { StateRoot string `pg:",pk,notnull"` Address string `pg:",pk,notnull"` - Event string `pg:",notnull,type:data_cap_balance_event_type"` - DataCap string `pg:",notnull,type:numeric"` + Event string `pg:",notnull,type:data_cap_balance_event_type"` + DataCap string `pg:",notnull,type:numeric"` + AddressType string `pg:",notnull"` } func (d *DataCapBalance) Persist(ctx context.Context, s model.StorageBatch, _ model.Version) error { diff --git a/model/chain/economics.go b/model/chain/economics.go index 33a8a42e..c13559f9 100644 --- a/model/chain/economics.go +++ b/model/chain/economics.go @@ -22,6 +22,7 @@ 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/schemas/v1/39_add_locked_fil_v2_chaineconomics.go b/schemas/v1/39_add_locked_fil_v2_chaineconomics.go new file mode 100644 index 00000000..b081fc86 --- /dev/null +++ b/schemas/v1/39_add_locked_fil_v2_chaineconomics.go @@ -0,0 +1,11 @@ +package v1 + +func init() { + patches.Register( + 39, + ` + ALTER TABLE {{ .SchemaName | default "public"}}.chain_economics ADD COLUMN IF NOT EXISTS locked_fil_v2 numeric DEFAULT 0; + ALTER TABLE {{ .SchemaName | default "public"}}.data_cap_balances ADD COLUMN IF NOT EXISTS address_type text DEFAULT ''; +`, + ) +} diff --git a/tasks/actorstate/datacap/balance.go b/tasks/actorstate/datacap/balance.go index 585cc8f7..611b7a85 100644 --- a/tasks/actorstate/datacap/balance.go +++ b/tasks/actorstate/datacap/balance.go @@ -11,18 +11,20 @@ import ( "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" "github.com/filecoin-project/lily/chain/actors/builtin/datacap" + "github.com/filecoin-project/lily/chain/actors/builtin/verifreg" "github.com/filecoin-project/lily/model" datacapmodel "github.com/filecoin-project/lily/model/actors/datacap" "github.com/filecoin-project/lily/tasks/actorstate" "github.com/filecoin-project/lotus/chain/types" + "github.com/filecoin-project/specs-actors/actors/builtin" ) var log = logging.Logger("lily/tasks/datacap") type BalanceExtractor struct{} -func (BalanceExtractor) Extract(ctx context.Context, a actorstate.ActorInfo, node actorstate.ActorStateAPI) (model.Persistable, error) { +func (extractor BalanceExtractor) Extract(ctx context.Context, a actorstate.ActorInfo, node actorstate.ActorStateAPI) (model.Persistable, error) { log.Debugw("extract", zap.String("extractor", "BalanceExtractor"), zap.Inline(a)) ctx, span := otel.Tracer("").Start(ctx, "BalancesExtractor.Extract") defer span.End() @@ -41,11 +43,12 @@ func (BalanceExtractor) Extract(ctx context.Context, a actorstate.ActorInfo, nod if !ec.HasPreviousState() { if err := ec.CurrState.ForEachClient(func(addr address.Address, dcap abi.StoragePower) error { balances = append(balances, &datacapmodel.DataCapBalance{ - Height: int64(ec.CurrTs.Height()), - StateRoot: ec.CurrTs.ParentState().String(), - Address: addr.String(), - Event: datacapmodel.Added, - DataCap: dcap.String(), + Height: int64(ec.CurrTs.Height()), + StateRoot: ec.CurrTs.ParentState().String(), + Address: addr.String(), + Event: datacapmodel.Added, + DataCap: dcap.String(), + AddressType: datacapmodel.VerifierClient, }) return nil }); err != nil { @@ -61,31 +64,87 @@ func (BalanceExtractor) Extract(ctx context.Context, a actorstate.ActorInfo, nod for _, change := range changes.Added { balances = append(balances, &datacapmodel.DataCapBalance{ - Height: int64(ec.CurrTs.Height()), - StateRoot: ec.CurrTs.ParentState().String(), - Address: change.Address.String(), - Event: datacapmodel.Added, - DataCap: change.DataCap.String(), + Height: int64(ec.CurrTs.Height()), + StateRoot: ec.CurrTs.ParentState().String(), + Address: change.Address.String(), + Event: datacapmodel.Added, + DataCap: change.DataCap.String(), + AddressType: datacapmodel.VerifierClient, }) + } for _, change := range changes.Removed { balances = append(balances, &datacapmodel.DataCapBalance{ - Height: int64(ec.CurrTs.Height()), - StateRoot: ec.CurrTs.ParentState().String(), - Address: change.Address.String(), - Event: datacapmodel.Removed, - DataCap: change.DataCap.String(), + Height: int64(ec.CurrTs.Height()), + StateRoot: ec.CurrTs.ParentState().String(), + Address: change.Address.String(), + Event: datacapmodel.Removed, + DataCap: change.DataCap.String(), + AddressType: datacapmodel.VerifierClient, }) } for _, change := range changes.Modified { balances = append(balances, &datacapmodel.DataCapBalance{ - Height: int64(ec.CurrTs.Height()), - StateRoot: ec.CurrTs.ParentState().String(), - Address: change.After.Address.String(), - Event: datacapmodel.Modified, - DataCap: change.After.DataCap.String(), + Height: int64(ec.CurrTs.Height()), + StateRoot: ec.CurrTs.ParentState().String(), + Address: change.After.Address.String(), + Event: datacapmodel.Modified, + DataCap: change.After.DataCap.String(), + AddressType: datacapmodel.VerifierClient, + }) + } + + // Handle the verifreg + verifregActor, actorErr := node.Actor(ctx, builtin.VerifiedRegistryActorAddr, a.Current.Key()) + if actorErr != nil { + log.Errorf("get error during getting VerifiedRegistry: %v", actorErr) + } + currentVerifregState, _ := verifreg.Load(node.Store(), verifregActor) + + preVerifregActor, actorErr := node.Actor(ctx, builtin.VerifiedRegistryActorAddr, a.Executed.Key()) + if actorErr != nil { + log.Errorf("get error during getting VerifiedRegistry: %v", actorErr) + } + preVerifregState, _ := verifreg.Load(node.Store(), preVerifregActor) + + verifierChanges, err := verifreg.DiffVerifiers(ctx, node.Store(), preVerifregState, currentVerifregState) + if err != nil { + return nil, fmt.Errorf("diffing verified registry verifiers: %w", err) + } + + // a new verifier was added + for _, change := range verifierChanges.Added { + balances = append(balances, &datacapmodel.DataCapBalance{ + Height: int64(ec.CurrTs.Height()), + StateRoot: ec.CurrTs.ParentState().String(), + Address: change.Address.String(), + Event: datacapmodel.Added, + DataCap: change.DataCap.String(), + AddressType: datacapmodel.Verifier, + }) + } + // a verifier was removed + for _, change := range verifierChanges.Removed { + balances = append(balances, &datacapmodel.DataCapBalance{ + Height: int64(ec.CurrTs.Height()), + StateRoot: ec.CurrTs.ParentState().String(), + Address: change.Address.String(), + Event: datacapmodel.Removed, + DataCap: change.DataCap.String(), + AddressType: datacapmodel.Verifier, + }) + } + // an existing verifier's DataCap changed + for _, change := range verifierChanges.Modified { + balances = append(balances, &datacapmodel.DataCapBalance{ + Height: int64(ec.CurrTs.Height()), + StateRoot: ec.CurrTs.ParentState().String(), + Address: change.After.Address.String(), + Event: datacapmodel.Modified, + DataCap: change.After.DataCap.String(), + AddressType: datacapmodel.Verifier, }) } return balances, nil diff --git a/tasks/chaineconomics/economics.go b/tasks/chaineconomics/economics.go index f8e1e9e5..ddff3284 100644 --- a/tasks/chaineconomics/economics.go +++ b/tasks/chaineconomics/economics.go @@ -8,9 +8,14 @@ import ( "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" + "github.com/filecoin-project/go-address" + "github.com/filecoin-project/lily/chain/actors/adt" + "github.com/filecoin-project/lily/chain/actors/builtin/miner" "github.com/filecoin-project/lily/model" chainmodel "github.com/filecoin-project/lily/model/chain" + actorstypes "github.com/filecoin-project/go-state-types/actors" + "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" ) @@ -22,6 +27,9 @@ type EconomicsStorage interface { type ChainEconomicsLens interface { CirculatingSupply(context.Context, *types.TipSet) (api.CirculatingSupply, error) + Actor(ctx context.Context, addr address.Address, tsk types.TipSetKey) (*types.Actor, error) + Store() adt.Store + MinerLoad(store adt.Store, act *types.Actor) (miner.State, error) } func ExtractChainEconomicsModel(ctx context.Context, node ChainEconomicsLens, ts *types.TipSet) (*chainmodel.ChainEconomics, error) { @@ -36,7 +44,7 @@ func ExtractChainEconomicsModel(ctx context.Context, node ChainEconomicsLens, ts return nil, fmt.Errorf("get circulating supply: %w", err) } - return &chainmodel.ChainEconomics{ + chainEconomic := &chainmodel.ChainEconomics{ Height: int64(ts.Height()), ParentStateRoot: ts.ParentState().String(), VestedFil: supply.FilVested.String(), @@ -45,5 +53,18 @@ func ExtractChainEconomicsModel(ctx context.Context, node ChainEconomicsLens, ts LockedFil: supply.FilLocked.String(), CirculatingFil: supply.FilCirculating.String(), FilReserveDisbursed: supply.FilReserveDisbursed.String(), - }, nil + } + + 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_test.go b/tasks/chaineconomics/economics_test.go index 58fe558c..b080956b 100644 --- a/tasks/chaineconomics/economics_test.go +++ b/tasks/chaineconomics/economics_test.go @@ -2,18 +2,23 @@ package chaineconomics import ( "context" + "fmt" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/filecoin-project/go-address" "github.com/filecoin-project/go-state-types/abi" + "github.com/filecoin-project/lily/chain/actors/adt" + "github.com/filecoin-project/lily/chain/actors/builtin/miner" "github.com/filecoin-project/lily/testutil" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/chain/types" ) +// nolint: revive type MockedChainEconomicsLens struct { mock.Mock } @@ -23,6 +28,16 @@ func (m *MockedChainEconomicsLens) CirculatingSupply(ctx context.Context, ts *ty return args.Get(0).(api.CirculatingSupply), args.Error(1) } +func (m *MockedChainEconomicsLens) Actor(_ context.Context, _ address.Address, _ types.TipSetKey) (*types.Actor, error) { + return nil, nil +} +func (m *MockedChainEconomicsLens) Store() adt.Store { + return nil +} +func (m *MockedChainEconomicsLens) MinerLoad(_ adt.Store, _ *types.Actor) (miner.State, error) { + return nil, fmt.Errorf("test error") +} + func TestEconomicsModelExtraction(t *testing.T) { ctx := context.Background()