Skip to content

Commit c91d948

Browse files
committed
sqlite: allow failed to successful and successful to failed state transition.
1 parent 6e044db commit c91d948

File tree

1 file changed

+47
-26
lines changed

1 file changed

+47
-26
lines changed

persist/sqlite/consensus.go

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -969,10 +969,13 @@ func applySuccessfulContracts(tx *txn, index types.ChainIndex, successful []type
969969
if state.Status == contracts.ContractStatusSuccessful {
970970
// skip update if the contract was already successful
971971
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))
976979
}
977980

978981
// update the contract's resolution index and status
@@ -989,14 +992,20 @@ func applySuccessfulContracts(tx *txn, index types.ChainIndex, successful []type
989992
return fmt.Errorf("failed to set contract %q status: %w", contractID, err)
990993
}
991994

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 {
997997
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+
}
10001009
}
10011010
}
10021011
return nil
@@ -1042,10 +1051,13 @@ func applyFailedContracts(tx *txn, failed []types.FileContractID) error {
10421051
if state.Status == contracts.ContractStatusFailed {
10431052
// skip update if the contract was already failed
10441053
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))
10491061
}
10501062

10511063
// update the contract's resolution index and status
@@ -1062,11 +1074,20 @@ func applyFailedContracts(tx *txn, failed []types.FileContractID) error {
10621074
return fmt.Errorf("failed to set contract %q status: %w", contractID, err)
10631075
}
10641076

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+
}
10701091
}
10711092
}
10721093
return nil
@@ -1113,7 +1134,7 @@ func revertContractFormation(tx *txn, reverted []types.FileContractElement) erro
11131134
if state.Status != contracts.ContractStatusActive {
11141135
// if the contract is not active, panic. Applies should have ensured
11151136
// 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))
11171138
}
11181139

11191140
// set the contract status to pending
@@ -1179,7 +1200,7 @@ func revertSuccessfulContracts(tx *txn, successful []types.FileContractID) error
11791200
if state.Status != contracts.ContractStatusSuccessful {
11801201
// if the contract is not successful, panic. Applies should have
11811202
// 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))
11831204
}
11841205

11851206
if res, err := updateStmt.Exec(encode(contractID)); err != nil {
@@ -1247,8 +1268,8 @@ func revertFailedContracts(tx *txn, failed []types.FileContractID) error {
12471268

12481269
if state.Status != contracts.ContractStatusFailed {
12491270
// 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))
12521273
} else if state.Status == contracts.ContractStatusFailed {
12531274
// skip update, most likely rescanning
12541275
continue
@@ -1501,10 +1522,10 @@ func applySuccessfulV2Contracts(tx *txn, index types.ChainIndex, status contract
15011522
// skip update if the contract was already successful.
15021523
// This should only happen during a rescan
15031524
continue
1504-
} else if state.Status != contracts.V2ContractStatusActive {
1525+
} else if state.Status != contracts.V2ContractStatusActive && state.Status != contracts.V2ContractStatusFailed {
15051526
// panic if the contract is not active. Proper reverts should have
15061527
// 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))
15081529
}
15091530

15101531
// update the contract's resolution index and status

0 commit comments

Comments
 (0)