Skip to content

Commit

Permalink
Merge pull request #460 from SiaFoundation/nate/allow-failed-state-tr…
Browse files Browse the repository at this point in the history
…ansition

Allow transitions between succesful and failed for logic updates
  • Loading branch information
n8maninger authored Sep 4, 2024
2 parents 6e044db + c91d948 commit dc762b8
Showing 1 changed file with 47 additions and 26 deletions.
73 changes: 47 additions & 26 deletions persist/sqlite/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -969,10 +969,13 @@ func applySuccessfulContracts(tx *txn, index types.ChainIndex, successful []type
if state.Status == contracts.ContractStatusSuccessful {
// skip update if the contract was already successful
continue
} else if state.Status != contracts.ContractStatusActive {
// panic if the contract is not active. Proper reverts should have
// ensured that this never happens.
panic(fmt.Errorf("unexpected contract state transition %q -> %q", state.Status, contracts.ContractStatusSuccessful))
} else if state.Status != contracts.ContractStatusActive && state.Status != contracts.ContractStatusFailed {
// panic if the contract is not active or failed. Proper reverts
// should have ensured that this never happens.
//
// note: going from failed -> successful is allowed in case
// of future logic changes.
panic(fmt.Errorf("unexpected contract state transition %q %q -> %q", contractID, state.Status, contracts.ContractStatusSuccessful))
}

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

// subtract the usage from the potential revenue metrics and add it to the
// earned revenue metrics
if err := updatePotentialRevenueMetrics(state.Usage, true, incrementCurrencyStat); err != nil {
return fmt.Errorf("failed to update potential revenue metrics: %w", err)
} else if err := updateEarnedRevenueMetrics(state.Usage, false, incrementCurrencyStat); err != nil {
// add the usage to the earned revenue metrics
if err := updateEarnedRevenueMetrics(state.Usage, false, incrementCurrencyStat); err != nil {
return fmt.Errorf("failed to update earned revenue metrics: %w", err)
} else if err := updateCollateralMetrics(state.LockedCollateral, state.Usage.RiskedCollateral, true, incrementCurrencyStat); err != nil {
return fmt.Errorf("failed to update collateral metrics: %w", err)
}

// if the state is failed, the potential revenue metrics have already
// been reduced. If the state is active, subtract the usage from the
// potential revenue metrics.
if state.Status == contracts.ContractStatusActive {
if err := updatePotentialRevenueMetrics(state.Usage, true, incrementCurrencyStat); err != nil {
return fmt.Errorf("failed to update potential revenue metrics: %w", err)
} else if err := updateCollateralMetrics(state.LockedCollateral, state.Usage.RiskedCollateral, true, incrementCurrencyStat); err != nil {
return fmt.Errorf("failed to update collateral metrics: %w", err)
}
}
}
return nil
Expand Down Expand Up @@ -1042,10 +1051,13 @@ func applyFailedContracts(tx *txn, failed []types.FileContractID) error {
if state.Status == contracts.ContractStatusFailed {
// skip update if the contract was already failed
continue
} else if state.Status != contracts.ContractStatusActive {
// panic if the contract is not active. Proper reverts should have
// ensured that this never happens.
panic(fmt.Errorf("unexpected contract state transition %q -> %q", state.Status, contracts.ContractStatusFailed))
} else if state.Status != contracts.ContractStatusActive && state.Status != contracts.ContractStatusSuccessful {
// panic if the contract is not active or successful. Proper reverts
// should have ensured that this never happens.
//
// note: going from successful -> failed is allowed in the case of
// future logic changes.
panic(fmt.Errorf("unexpected contract state transition %q %q -> %q", contractID, state.Status, contracts.ContractStatusFailed))
}

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

// subtract the usage from the potential revenue metrics
if err := updatePotentialRevenueMetrics(state.Usage, true, incrementCurrencyStat); err != nil {
return fmt.Errorf("failed to update potential revenue metrics: %w", err)
} else if err := updateCollateralMetrics(state.LockedCollateral, state.Usage.RiskedCollateral, true, incrementCurrencyStat); err != nil {
return fmt.Errorf("failed to update collateral metrics: %w", err)
if state.Status == contracts.ContractStatusActive {
// if the contract is active, subtract the usage from the potential
// revenue metrics and the collateral metrics.
if err := updatePotentialRevenueMetrics(state.Usage, true, incrementCurrencyStat); err != nil {
return fmt.Errorf("failed to update potential revenue metrics: %w", err)
} else if err := updateCollateralMetrics(state.LockedCollateral, state.Usage.RiskedCollateral, true, incrementCurrencyStat); err != nil {
return fmt.Errorf("failed to update collateral metrics: %w", err)
}
} else if state.Status == contracts.ContractStatusSuccessful {
// if the contract is successful, subtract the usage from the earned
// revenue metrics.
if err := updateEarnedRevenueMetrics(state.Usage, true, incrementCurrencyStat); err != nil {
return fmt.Errorf("failed to update earned revenue metrics: %w", err)
}
}
}
return nil
Expand Down Expand Up @@ -1113,7 +1134,7 @@ func revertContractFormation(tx *txn, reverted []types.FileContractElement) erro
if state.Status != contracts.ContractStatusActive {
// if the contract is not active, panic. Applies should have ensured
// that this never happens.
panic(fmt.Errorf("unexpected contract state transition %q -> %q", state.Status, contracts.ContractStatusPending))
panic(fmt.Errorf("unexpected contract state transition %q %q -> %q", fce.ID, state.Status, contracts.ContractStatusPending))
}

// set the contract status to pending
Expand Down Expand Up @@ -1179,7 +1200,7 @@ func revertSuccessfulContracts(tx *txn, successful []types.FileContractID) error
if state.Status != contracts.ContractStatusSuccessful {
// if the contract is not successful, panic. Applies should have
// ensured that this never happens.
panic(fmt.Errorf("unexpected contract state transition %q -> %q", state.Status, contracts.ContractStatusActive))
panic(fmt.Errorf("unexpected contract state transition %q %q -> %q", contractID, state.Status, contracts.ContractStatusActive))
}

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

if state.Status != contracts.ContractStatusFailed {
// panic if the contract is not failed. Proper reverts should have
// ensured that this never happens.
panic(fmt.Errorf("unexpected contract state transition %q -> %q", state.Status, contracts.ContractStatusFailed))
// ensured that this never happens.
panic(fmt.Errorf("unexpected contract state transition %q %q -> %q", contractID, state.Status, contracts.ContractStatusFailed))
} else if state.Status == contracts.ContractStatusFailed {
// skip update, most likely rescanning
continue
Expand Down Expand Up @@ -1501,10 +1522,10 @@ func applySuccessfulV2Contracts(tx *txn, index types.ChainIndex, status contract
// skip update if the contract was already successful.
// This should only happen during a rescan
continue
} else if state.Status != contracts.V2ContractStatusActive {
} else if state.Status != contracts.V2ContractStatusActive && state.Status != contracts.V2ContractStatusFailed {
// panic if the contract is not active. Proper reverts should have
// ensured that this never happens.
panic(fmt.Errorf("unexpected contract state transition %q -> %q", state.Status, contracts.ContractStatusSuccessful))
panic(fmt.Errorf("unexpected contract state transition %q %q -> %q", contractID, state.Status, contracts.V2ContractStatusSuccessful))
}

// update the contract's resolution index and status
Expand Down

0 comments on commit dc762b8

Please sign in to comment.