@@ -23,7 +23,14 @@ import (
2323 "github.com/filecoin-project/go-address"
2424 "github.com/filecoin-project/go-state-types/abi"
2525 "github.com/filecoin-project/go-state-types/big"
26-
26+ miner14 "github.com/filecoin-project/go-state-types/builtin/v14/miner"
27+ smoothing14 "github.com/filecoin-project/go-state-types/builtin/v14/util/smoothing"
28+ miner15 "github.com/filecoin-project/go-state-types/builtin/v15/miner"
29+ smoothing15 "github.com/filecoin-project/go-state-types/builtin/v15/util/smoothing"
30+ gststore "github.com/filecoin-project/go-state-types/store"
31+
32+ "github.com/filecoin-project/lotus/api"
33+ "github.com/filecoin-project/lotus/blockstore"
2734 "github.com/filecoin-project/lotus/build/buildconstants"
2835 "github.com/filecoin-project/lotus/chain/actors/adt"
2936 "github.com/filecoin-project/lotus/chain/actors/builtin"
@@ -69,6 +76,7 @@ var auditsCmd = &cli.Command{
6976 chainBalanceSanityCheckCmd ,
7077 chainBalanceStateCmd ,
7178 chainPledgeCmd ,
79+ chainFip0081PledgeCmd ,
7280 fillBalancesCmd ,
7381 duplicatedMessagesCmd ,
7482 },
@@ -941,3 +949,335 @@ var fillBalancesCmd = &cli.Command{
941949 return nil
942950 },
943951}
952+
953+ var chainFip0081PledgeCmd = & cli.Command {
954+ Name : "fip0081-pledge" ,
955+ Description : "Calculate sector pledge values comparing current to pre-FIP-0081" ,
956+ ArgsUsage : "[epoch number]" ,
957+ Action : func (cctx * cli.Context ) error {
958+
959+ ctx := lcli .ReqContext (cctx )
960+
961+ api , acloser , err := lcli .GetFullNodeAPIV1 (cctx )
962+ if err != nil {
963+ return err
964+ }
965+ defer acloser ()
966+
967+ var ts * types.TipSet
968+ if cctx .Args ().Present () {
969+ epoch , err := strconv .ParseInt (cctx .Args ().First (), 10 , 64 )
970+ if err != nil {
971+ return xerrors .Errorf ("parsing epoch arg: %w" , err )
972+ }
973+ ts , err = api .ChainGetTipSetByHeight (ctx , abi .ChainEpoch (epoch ), types .EmptyTSK )
974+ if err != nil {
975+ return err
976+ }
977+ } else {
978+ ts , err = api .ChainHead (ctx )
979+ if err != nil {
980+ return err
981+ }
982+ }
983+
984+ cases := []struct {
985+ sectorSize abi.SectorSize
986+ verifiedSize uint64
987+ duration abi.ChainEpoch
988+ }{
989+ {
990+ sectorSize : 2 << 10 ,
991+ verifiedSize : 2 << 10 ,
992+ duration : builtin .EpochsInYear ,
993+ },
994+ {
995+ sectorSize : 2 << 10 ,
996+ verifiedSize : (2 << 10 ) / 2 ,
997+ duration : builtin .EpochsInYear ,
998+ },
999+ {
1000+ sectorSize : 2 << 10 ,
1001+ verifiedSize : 0 ,
1002+ duration : builtin .EpochsInYear ,
1003+ },
1004+ {
1005+ sectorSize : 2 << 10 ,
1006+ verifiedSize : 2 << 10 ,
1007+ duration : 3 * builtin .EpochsInYear ,
1008+ },
1009+ {
1010+ sectorSize : 2 << 10 ,
1011+ verifiedSize : (2 << 10 ) / 2 ,
1012+ duration : 3 * builtin .EpochsInYear ,
1013+ },
1014+ {
1015+ sectorSize : 2 << 10 ,
1016+ verifiedSize : 0 ,
1017+ duration : 3 * builtin .EpochsInYear ,
1018+ },
1019+ {
1020+ sectorSize : 32 << 30 ,
1021+ verifiedSize : 32 << 30 ,
1022+ duration : builtin .EpochsInYear ,
1023+ },
1024+ {
1025+ sectorSize : 32 << 30 ,
1026+ verifiedSize : (32 << 30 ) / 2 ,
1027+ duration : builtin .EpochsInYear ,
1028+ },
1029+ {
1030+ sectorSize : 32 << 30 ,
1031+ verifiedSize : 0 ,
1032+ duration : builtin .EpochsInYear ,
1033+ },
1034+ {
1035+ sectorSize : 32 << 30 ,
1036+ verifiedSize : 32 << 30 ,
1037+ duration : 3 * builtin .EpochsInYear ,
1038+ },
1039+ {
1040+ sectorSize : 32 << 30 ,
1041+ verifiedSize : (32 << 30 ) / 2 ,
1042+ duration : 3 * builtin .EpochsInYear ,
1043+ },
1044+ {
1045+ sectorSize : 32 << 30 ,
1046+ verifiedSize : 0 ,
1047+ duration : 3 * builtin .EpochsInYear ,
1048+ },
1049+ {
1050+ sectorSize : 64 << 30 ,
1051+ verifiedSize : 64 << 30 ,
1052+ duration : builtin .EpochsInYear ,
1053+ },
1054+ {
1055+ sectorSize : 64 << 30 ,
1056+ verifiedSize : (64 << 30 ) / 2 ,
1057+ duration : builtin .EpochsInYear ,
1058+ },
1059+ {
1060+ sectorSize : 64 << 30 ,
1061+ verifiedSize : 0 ,
1062+ duration : builtin .EpochsInYear ,
1063+ },
1064+ {
1065+ sectorSize : 64 << 30 ,
1066+ verifiedSize : 64 << 30 ,
1067+ duration : 3 * builtin .EpochsInYear ,
1068+ },
1069+ {
1070+ sectorSize : 64 << 30 ,
1071+ verifiedSize : (64 << 30 ) / 2 ,
1072+ duration : 3 * builtin .EpochsInYear ,
1073+ },
1074+ {
1075+ sectorSize : 64 << 30 ,
1076+ verifiedSize : 0 ,
1077+ duration : 3 * builtin .EpochsInYear ,
1078+ },
1079+ }
1080+
1081+ fmt .Printf ("\033 [3mCalculating at epoch %d\033 [0m\n " , ts .Height ())
1082+ fmt .Printf (" \033 [1mSector Size\033 [0m | \033 [1mVerified %%\033 [0m | \033 [1mDuration\033 [0m | \033 [1mActual\033 [0m | \033 [1mPre-FIP-0081\033 [0m | \033 [1mDifference\033 [0m\n " )
1083+ fmt .Println (strings .Repeat ("-" , 119 ))
1084+
1085+ for _ , c := range cases {
1086+ pledge , err := api .StateMinerInitialPledgeForSector (ctx , c .duration , c .sectorSize , c .verifiedSize , ts .Key ())
1087+ if err != nil {
1088+ return err
1089+ }
1090+ newPledge , err := postFip0081StateMinerInitialPledgeForSector (ctx , api , c .duration , c .sectorSize , c .verifiedSize , ts )
1091+ if err != nil {
1092+ return err
1093+ }
1094+ if ! pledge .Equals (newPledge ) {
1095+ return xerrors .Errorf ("failed to sanity check StateMinerInitialPledgeForSector calculation!" )
1096+ }
1097+ oldPledge , err := preFip0081StateMinerInitialPledgeForSector (ctx , api , c .duration , c .sectorSize , c .verifiedSize , ts )
1098+ if err != nil {
1099+ return err
1100+ }
1101+
1102+ fmt .Printf (" %-11s | % 4.f%% | %0.f year(s) | %-24s | %-24s | %s\n " ,
1103+ c .sectorSize .ShortString (),
1104+ float64 (c .verifiedSize )/ float64 (c .sectorSize )* 100 ,
1105+ float64 (c .duration )/ builtin .EpochsInYear ,
1106+ types .FIL (pledge ).String (),
1107+ types .FIL (oldPledge ).String (),
1108+ types .FIL (types .BigSub (pledge , oldPledge )).String (),
1109+ )
1110+ }
1111+ fmt .Println (strings .Repeat ("-" , 119 ))
1112+
1113+ return nil
1114+ },
1115+ }
1116+
1117+ // from itests/migration_test.go
1118+
1119+ // preFip0081StateMinerInitialPledgeForSector is the same calculation as StateMinerInitialPledgeForSector
1120+ // but uses miner14's version of the calculation without the FIP-0081 changes.
1121+ func preFip0081StateMinerInitialPledgeForSector (
1122+ ctx context.Context ,
1123+ client api.FullNode ,
1124+ sectorDuration abi.ChainEpoch ,
1125+ sectorSize abi.SectorSize ,
1126+ verifiedSize uint64 ,
1127+ ts * types.TipSet ,
1128+ ) (types.BigInt , error ) {
1129+ bs := blockstore .NewAPIBlockstore (client )
1130+ ctxStore := gststore .WrapBlockStore (ctx , bs )
1131+
1132+ circSupply , err := client .StateVMCirculatingSupplyInternal (ctx , ts .Key ())
1133+ if err != nil {
1134+ return types .NewInt (0 ), err
1135+ }
1136+
1137+ powerActor , err := client .StateGetActor (ctx , power .Address , ts .Key ())
1138+ if err != nil {
1139+ return types .NewInt (0 ), err
1140+ }
1141+
1142+ powerState , err := power .Load (ctxStore , powerActor )
1143+ if err != nil {
1144+ return types .NewInt (0 ), err
1145+ }
1146+
1147+ rewardActor , err := client .StateGetActor (ctx , reward .Address , ts .Key ())
1148+ if err != nil {
1149+ return types .NewInt (0 ), err
1150+ }
1151+
1152+ rewardState , err := reward .Load (ctxStore , rewardActor )
1153+ if err != nil {
1154+ return types .NewInt (0 ), err
1155+ }
1156+
1157+ networkQAPower , err := powerState .TotalPowerSmoothed ()
1158+ if err != nil {
1159+ return types .NewInt (0 ), err
1160+ }
1161+
1162+ verifiedWeight := big .Mul (big .NewIntUnsigned (verifiedSize ), big .NewInt (int64 (sectorDuration )))
1163+ sectorWeight := builtin .QAPowerForWeight (sectorSize , sectorDuration , verifiedWeight )
1164+
1165+ thisEpochBaselinePower , err := rewardState .(interface {
1166+ ThisEpochBaselinePower () (abi.StoragePower , error )
1167+ }).ThisEpochBaselinePower ()
1168+ if err != nil {
1169+ return types .NewInt (0 ), err
1170+ }
1171+ thisEpochRewardSmoothed , err := rewardState .(interface {
1172+ ThisEpochRewardSmoothed () (builtin.FilterEstimate , error )
1173+ }).ThisEpochRewardSmoothed ()
1174+ if err != nil {
1175+ return types .NewInt (0 ), err
1176+ }
1177+
1178+ rewardEstimate := smoothing14.FilterEstimate {
1179+ PositionEstimate : thisEpochRewardSmoothed .PositionEstimate ,
1180+ VelocityEstimate : thisEpochRewardSmoothed .VelocityEstimate ,
1181+ }
1182+ networkQAPowerEstimate := smoothing14.FilterEstimate {
1183+ PositionEstimate : networkQAPower .PositionEstimate ,
1184+ VelocityEstimate : networkQAPower .VelocityEstimate ,
1185+ }
1186+
1187+ initialPledge := miner14 .InitialPledgeForPower (
1188+ sectorWeight ,
1189+ thisEpochBaselinePower ,
1190+ rewardEstimate ,
1191+ networkQAPowerEstimate ,
1192+ circSupply .FilCirculating ,
1193+ )
1194+
1195+ var initialPledgeNum = types .NewInt (110 )
1196+ var initialPledgeDen = types .NewInt (100 )
1197+
1198+ return types .BigDiv (types .BigMul (initialPledge , initialPledgeNum ), initialPledgeDen ), nil
1199+ }
1200+
1201+ // postFip0081StateMinerInitialPledgeForSector should be the same calculation as StateMinerInitialPledgeForSector,
1202+ // it's here for sanity checking.
1203+ func postFip0081StateMinerInitialPledgeForSector (
1204+ ctx context.Context ,
1205+ client api.FullNode ,
1206+ sectorDuration abi.ChainEpoch ,
1207+ sectorSize abi.SectorSize ,
1208+ verifiedSize uint64 ,
1209+ ts * types.TipSet ,
1210+ ) (types.BigInt , error ) {
1211+ bs := blockstore .NewAPIBlockstore (client )
1212+ ctxStore := gststore .WrapBlockStore (ctx , bs )
1213+
1214+ circSupply , err := client .StateVMCirculatingSupplyInternal (ctx , ts .Key ())
1215+ if err != nil {
1216+ return types .NewInt (0 ), err
1217+ }
1218+
1219+ powerActor , err := client .StateGetActor (ctx , power .Address , ts .Key ())
1220+ if err != nil {
1221+ return types .NewInt (0 ), err
1222+ }
1223+
1224+ powerState , err := power .Load (ctxStore , powerActor )
1225+ if err != nil {
1226+ return types .NewInt (0 ), err
1227+ }
1228+
1229+ rewardActor , err := client .StateGetActor (ctx , reward .Address , ts .Key ())
1230+ if err != nil {
1231+ return types .NewInt (0 ), err
1232+ }
1233+
1234+ rewardState , err := reward .Load (ctxStore , rewardActor )
1235+ if err != nil {
1236+ return types .NewInt (0 ), err
1237+ }
1238+
1239+ networkQAPower , err := powerState .TotalPowerSmoothed ()
1240+ if err != nil {
1241+ return types .NewInt (0 ), err
1242+ }
1243+
1244+ verifiedWeight := big .Mul (big .NewIntUnsigned (verifiedSize ), big .NewInt (int64 (sectorDuration )))
1245+ sectorWeight := builtin .QAPowerForWeight (sectorSize , sectorDuration , verifiedWeight )
1246+
1247+ thisEpochBaselinePower , err := rewardState .(interface {
1248+ ThisEpochBaselinePower () (abi.StoragePower , error )
1249+ }).ThisEpochBaselinePower ()
1250+ if err != nil {
1251+ return types .NewInt (0 ), err
1252+ }
1253+ thisEpochRewardSmoothed , err := rewardState .(interface {
1254+ ThisEpochRewardSmoothed () (builtin.FilterEstimate , error )
1255+ }).ThisEpochRewardSmoothed ()
1256+ if err != nil {
1257+ return types .NewInt (0 ), err
1258+ }
1259+
1260+ rewardEstimate := smoothing15.FilterEstimate {
1261+ PositionEstimate : thisEpochRewardSmoothed .PositionEstimate ,
1262+ VelocityEstimate : thisEpochRewardSmoothed .VelocityEstimate ,
1263+ }
1264+ networkQAPowerEstimate := smoothing15.FilterEstimate {
1265+ PositionEstimate : networkQAPower .PositionEstimate ,
1266+ VelocityEstimate : networkQAPower .VelocityEstimate ,
1267+ }
1268+
1269+ initialPledge := miner15 .InitialPledgeForPower (
1270+ sectorWeight ,
1271+ thisEpochBaselinePower ,
1272+ rewardEstimate ,
1273+ networkQAPowerEstimate ,
1274+ circSupply .FilCirculating ,
1275+ int64 (ts .Height ())- powerState .RampStartEpoch (),
1276+ powerState .RampDurationEpochs (),
1277+ )
1278+
1279+ var initialPledgeNum = types .NewInt (110 )
1280+ var initialPledgeDen = types .NewInt (100 )
1281+
1282+ return types .BigDiv (types .BigMul (initialPledge , initialPledgeNum ), initialPledgeDen ), nil
1283+ }
0 commit comments