@@ -969,10 +969,13 @@ func applySuccessfulContracts(tx *txn, index types.ChainIndex, successful []type
969
969
if state .Status == contracts .ContractStatusSuccessful {
970
970
// skip update if the contract was already successful
971
971
continue
972
- } else if state .Status != contracts .ContractStatusActive {
973
- // panic if the contract is not active. Proper reverts should have
974
- // ensured that this never happens.
975
- panic (fmt .Errorf ("unexpected contract state transition %q -> %q" , state .Status , contracts .ContractStatusSuccessful ))
972
+ } else if state .Status != contracts .ContractStatusActive && state .Status != contracts .ContractStatusFailed {
973
+ // panic if the contract is not active or failed. Proper reverts
974
+ // should have ensured that this never happens.
975
+ //
976
+ // note: going from failed -> successful is allowed in case
977
+ // of future logic changes.
978
+ panic (fmt .Errorf ("unexpected contract state transition %q %q -> %q" , contractID , state .Status , contracts .ContractStatusSuccessful ))
976
979
}
977
980
978
981
// update the contract's resolution index and status
@@ -989,14 +992,20 @@ func applySuccessfulContracts(tx *txn, index types.ChainIndex, successful []type
989
992
return fmt .Errorf ("failed to set contract %q status: %w" , contractID , err )
990
993
}
991
994
992
- // subtract the usage from the potential revenue metrics and add it to the
993
- // earned revenue metrics
994
- if err := updatePotentialRevenueMetrics (state .Usage , true , incrementCurrencyStat ); err != nil {
995
- return fmt .Errorf ("failed to update potential revenue metrics: %w" , err )
996
- } else if err := updateEarnedRevenueMetrics (state .Usage , false , incrementCurrencyStat ); err != nil {
995
+ // add the usage to the earned revenue metrics
996
+ if err := updateEarnedRevenueMetrics (state .Usage , false , incrementCurrencyStat ); err != nil {
997
997
return fmt .Errorf ("failed to update earned revenue metrics: %w" , err )
998
- } else if err := updateCollateralMetrics (state .LockedCollateral , state .Usage .RiskedCollateral , true , incrementCurrencyStat ); err != nil {
999
- return fmt .Errorf ("failed to update collateral metrics: %w" , err )
998
+ }
999
+
1000
+ // if the state is failed, the potential revenue metrics have already
1001
+ // been reduced. If the state is active, subtract the usage from the
1002
+ // potential revenue metrics.
1003
+ if state .Status == contracts .ContractStatusActive {
1004
+ if err := updatePotentialRevenueMetrics (state .Usage , true , incrementCurrencyStat ); err != nil {
1005
+ return fmt .Errorf ("failed to update potential revenue metrics: %w" , err )
1006
+ } else if err := updateCollateralMetrics (state .LockedCollateral , state .Usage .RiskedCollateral , true , incrementCurrencyStat ); err != nil {
1007
+ return fmt .Errorf ("failed to update collateral metrics: %w" , err )
1008
+ }
1000
1009
}
1001
1010
}
1002
1011
return nil
@@ -1042,10 +1051,13 @@ func applyFailedContracts(tx *txn, failed []types.FileContractID) error {
1042
1051
if state .Status == contracts .ContractStatusFailed {
1043
1052
// skip update if the contract was already failed
1044
1053
continue
1045
- } else if state .Status != contracts .ContractStatusActive {
1046
- // panic if the contract is not active. Proper reverts should have
1047
- // ensured that this never happens.
1048
- panic (fmt .Errorf ("unexpected contract state transition %q -> %q" , state .Status , contracts .ContractStatusFailed ))
1054
+ } else if state .Status != contracts .ContractStatusActive && state .Status != contracts .ContractStatusSuccessful {
1055
+ // panic if the contract is not active or successful. Proper reverts
1056
+ // should have ensured that this never happens.
1057
+ //
1058
+ // note: going from successful -> failed is allowed in the case of
1059
+ // future logic changes.
1060
+ panic (fmt .Errorf ("unexpected contract state transition %q %q -> %q" , contractID , state .Status , contracts .ContractStatusFailed ))
1049
1061
}
1050
1062
1051
1063
// update the contract's resolution index and status
@@ -1062,11 +1074,20 @@ func applyFailedContracts(tx *txn, failed []types.FileContractID) error {
1062
1074
return fmt .Errorf ("failed to set contract %q status: %w" , contractID , err )
1063
1075
}
1064
1076
1065
- // subtract the usage from the potential revenue metrics
1066
- if err := updatePotentialRevenueMetrics (state .Usage , true , incrementCurrencyStat ); err != nil {
1067
- return fmt .Errorf ("failed to update potential revenue metrics: %w" , err )
1068
- } else if err := updateCollateralMetrics (state .LockedCollateral , state .Usage .RiskedCollateral , true , incrementCurrencyStat ); err != nil {
1069
- return fmt .Errorf ("failed to update collateral metrics: %w" , err )
1077
+ if state .Status == contracts .ContractStatusActive {
1078
+ // if the contract is active, subtract the usage from the potential
1079
+ // revenue metrics and the collateral metrics.
1080
+ if err := updatePotentialRevenueMetrics (state .Usage , true , incrementCurrencyStat ); err != nil {
1081
+ return fmt .Errorf ("failed to update potential revenue metrics: %w" , err )
1082
+ } else if err := updateCollateralMetrics (state .LockedCollateral , state .Usage .RiskedCollateral , true , incrementCurrencyStat ); err != nil {
1083
+ return fmt .Errorf ("failed to update collateral metrics: %w" , err )
1084
+ }
1085
+ } else if state .Status == contracts .ContractStatusSuccessful {
1086
+ // if the contract is successful, subtract the usage from the earned
1087
+ // revenue metrics.
1088
+ if err := updateEarnedRevenueMetrics (state .Usage , true , incrementCurrencyStat ); err != nil {
1089
+ return fmt .Errorf ("failed to update earned revenue metrics: %w" , err )
1090
+ }
1070
1091
}
1071
1092
}
1072
1093
return nil
@@ -1113,7 +1134,7 @@ func revertContractFormation(tx *txn, reverted []types.FileContractElement) erro
1113
1134
if state .Status != contracts .ContractStatusActive {
1114
1135
// if the contract is not active, panic. Applies should have ensured
1115
1136
// that this never happens.
1116
- panic (fmt .Errorf ("unexpected contract state transition %q -> %q" , state .Status , contracts .ContractStatusPending ))
1137
+ panic (fmt .Errorf ("unexpected contract state transition %q %q -> %q" , fce . ID , state .Status , contracts .ContractStatusPending ))
1117
1138
}
1118
1139
1119
1140
// set the contract status to pending
@@ -1179,7 +1200,7 @@ func revertSuccessfulContracts(tx *txn, successful []types.FileContractID) error
1179
1200
if state .Status != contracts .ContractStatusSuccessful {
1180
1201
// if the contract is not successful, panic. Applies should have
1181
1202
// ensured that this never happens.
1182
- panic (fmt .Errorf ("unexpected contract state transition %q -> %q" , state .Status , contracts .ContractStatusActive ))
1203
+ panic (fmt .Errorf ("unexpected contract state transition %q %q -> %q" , contractID , state .Status , contracts .ContractStatusActive ))
1183
1204
}
1184
1205
1185
1206
if res , err := updateStmt .Exec (encode (contractID )); err != nil {
@@ -1247,8 +1268,8 @@ func revertFailedContracts(tx *txn, failed []types.FileContractID) error {
1247
1268
1248
1269
if state .Status != contracts .ContractStatusFailed {
1249
1270
// panic if the contract is not failed. Proper reverts should have
1250
- // ensured that this never happens.
1251
- panic (fmt .Errorf ("unexpected contract state transition %q -> %q" , state .Status , contracts .ContractStatusFailed ))
1271
+ // ensured that this never happens.
1272
+ panic (fmt .Errorf ("unexpected contract state transition %q %q -> %q" , contractID , state .Status , contracts .ContractStatusFailed ))
1252
1273
} else if state .Status == contracts .ContractStatusFailed {
1253
1274
// skip update, most likely rescanning
1254
1275
continue
@@ -1501,10 +1522,10 @@ func applySuccessfulV2Contracts(tx *txn, index types.ChainIndex, status contract
1501
1522
// skip update if the contract was already successful.
1502
1523
// This should only happen during a rescan
1503
1524
continue
1504
- } else if state .Status != contracts .V2ContractStatusActive {
1525
+ } else if state .Status != contracts .V2ContractStatusActive && state . Status != contracts . V2ContractStatusFailed {
1505
1526
// panic if the contract is not active. Proper reverts should have
1506
1527
// ensured that this never happens.
1507
- panic (fmt .Errorf ("unexpected contract state transition %q -> %q" , state .Status , contracts .ContractStatusSuccessful ))
1528
+ panic (fmt .Errorf ("unexpected contract state transition %q %q -> %q" , contractID , state .Status , contracts .V2ContractStatusSuccessful ))
1508
1529
}
1509
1530
1510
1531
// update the contract's resolution index and status
0 commit comments