-
Notifications
You must be signed in to change notification settings - Fork 27
migrate and enhance penalties subsuite from chain-validation. #108
Changes from 3 commits
aab97f6
074d6cb
50bfb82
2740326
3f9c349
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,13 +37,14 @@ import ( | |
type TipsetVectorBuilder struct { | ||
*BuilderCommon | ||
|
||
// StagedMessages and tmpStateTracker are the staging area for messages. | ||
StagedMessages *Messages | ||
tmpStateTracker *StateTracker | ||
// StagedMessages is a staging area for messages. | ||
StagedMessages *Messages | ||
// StateTracker is used for staging messages, and it's scrapped and replaced | ||
// by a fork at the PreRoot when committing applies. | ||
StateTracker *StateTracker | ||
Comment on lines
+40
to
+44
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Simplified the temporary state tracker construction here. We now just have one state tracker, and we replace it in |
||
|
||
InitialEpoch abi.ChainEpoch | ||
Tipsets *TipsetSeq | ||
StateTracker *StateTracker | ||
Rewards *Rewards | ||
|
||
PreRoot cid.Cid | ||
|
@@ -79,11 +80,6 @@ func TipsetVector(metadata *schema.Metadata, selector schema.Selector, mode Mode | |
return b.Tipsets.Messages() | ||
}, | ||
stateTracker: func() *StateTracker { | ||
// if we're in the preconditions stage, return the staging state tracker. | ||
// else, return the definite stage tracker. | ||
if b.Stage == StageApplies { | ||
return b.tmpStateTracker | ||
} | ||
return b.StateTracker | ||
}, | ||
actors: func() *Actors { return bc.Actors }, | ||
|
@@ -131,8 +127,7 @@ func (b *TipsetVectorBuilder) CommitPreconditions() { | |
// update the internal state. | ||
// create a staging state tracker that will be used during applies. | ||
// create the message staging area, linked to the temporary state tracker. | ||
b.tmpStateTracker = b.StateTracker.Fork(preroot) | ||
b.StagedMessages = NewMessages(b.BuilderCommon, b.tmpStateTracker) | ||
b.StagedMessages = NewMessages(b.BuilderCommon, b.StateTracker) | ||
|
||
b.Stage = StageApplies | ||
b.Assert.enterStage(StageApplies) | ||
|
@@ -153,6 +148,9 @@ func (b *TipsetVectorBuilder) CommitApplies() { | |
panic("called CommitApplies at the wrong time") | ||
} | ||
|
||
// discard the temporary state, and fork at the preroot. | ||
b.StateTracker = b.StateTracker.Fork(b.PreRoot) | ||
|
||
var ( | ||
ds = b.StateTracker.Stores.Datastore | ||
bs = b.StateTracker.Stores.Blockstore | ||
|
@@ -163,7 +161,7 @@ func (b *TipsetVectorBuilder) CommitApplies() { | |
// instantiate the reward tracker | ||
// record a rewards observation at the initial epoch. | ||
b.Rewards = NewRewards(b.BuilderCommon, b.StateTracker) | ||
b.Rewards.RecordAt(b.InitialEpoch) | ||
b.Rewards.RecordAt(0) | ||
|
||
// Initialize Postconditions on the vector; set the preroot as the temporary | ||
// postcondition root. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,36 +12,37 @@ const ( | |
overuseDen = 10 | ||
) | ||
|
||
// CalculateDeduction returns the balance that shall be deducted from the | ||
// CalculateSenderDeduction returns the balance that shall be deducted from the | ||
// sender's account as a result of applying this message. | ||
func CalculateDeduction(am *ApplicableMessage) big.Int { | ||
func CalculateSenderDeduction(am *ApplicableMessage) big.Int { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. More explicit naming to reduce cognitive load. |
||
if am.Result.GasUsed == 0 { | ||
return big.Zero() | ||
} | ||
|
||
m := am.Message | ||
minerReward := GetMinerReward(m.GasLimit, m.GasPremium) // goes to the miner | ||
burn := CalculateBurn(m.GasLimit, am.Result.GasUsed) // vanishes | ||
deducted := big.Add(minerReward, burn) // sum of gas accrued | ||
|
||
var ( | ||
minerReward = GetMinerReward(am) // goes to the miner | ||
burn = CalculateBurntGas(am) // vanishes | ||
deducted = big.Add(minerReward, burn) // sum of gas accrued | ||
) | ||
if am.Result.ExitCode.IsSuccess() { | ||
deducted = big.Add(deducted, m.Value) // message value | ||
deducted = big.Add(deducted, am.Message.Value) // message value | ||
} | ||
return deducted | ||
} | ||
|
||
// GetMinerReward returns the amount that the miner gets to keep, aka. miner tip. | ||
func GetMinerReward(gasLimit int64, gasPremium abi.TokenAmount) abi.TokenAmount { | ||
return big.Mul(big.NewInt(gasLimit), gasPremium) | ||
} | ||
|
||
func GetMinerPenalty(gasLimit int64) big.Int { | ||
return big.Mul(lotus.BaseFee, big.NewInt(gasLimit)) | ||
func GetMinerReward(am *ApplicableMessage) abi.TokenAmount { | ||
gasLimit := big.NewInt(am.Message.GasLimit) | ||
gasPremium := am.Message.GasPremium | ||
return big.Mul(gasLimit, gasPremium) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Calculating the miner penalty is not as straightforward, and this function wasn't even used in chain-validation. Nuking it. |
||
|
||
// CalculateBurn calcualtes the amount that will be burnt, a function of the | ||
// CalculateBurntGas calculates the amount that will be burnt, a function of the | ||
// gas limit and the gas actually used. | ||
func CalculateBurn(gasLimit int64, gasUsed int64) big.Int { | ||
func CalculateBurntGas(am *ApplicableMessage) big.Int { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. More explicit naming. This calculates burnt gas. Miner penalties are also burnt, and I needed to disambiguate. |
||
gasLimit := am.Message.GasLimit | ||
gasUsed := am.Result.GasUsed | ||
|
||
over := gasLimit - (overuseNum*gasUsed)/overuseDen | ||
if over < 0 { | ||
over = 0 | ||
|
@@ -52,7 +53,9 @@ func CalculateBurn(gasLimit int64, gasUsed int64) big.Int { | |
|
||
overestimateGas := big.NewInt(gasLimit - gasUsed) | ||
overestimateGas = big.Mul(overestimateGas, big.NewInt(over)) | ||
overestimateGas = big.Div(overestimateGas, big.NewInt(gasUsed)) | ||
if gasUsed != 0 { | ||
overestimateGas = big.Div(overestimateGas, big.NewInt(gasUsed)) | ||
} | ||
Comment on lines
+56
to
+58
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoiding divisions by zero. |
||
|
||
totalBurnGas := big.Add(overestimateGas, big.NewInt(gasUsed)) | ||
return big.Mul(lotus.BaseFee, totalBurnGas) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -115,7 +115,7 @@ func (m *Messages) ApplyOne(am *ApplicableMessage) { | |
} | ||
// verify that preceding messages have been applied. | ||
// this will abort if unsatisfied. | ||
m.bc.Assert.Nil(other.Result, "preceding messages must have been applied when calling Apply*; index of first unapplied: %d", i) | ||
m.bc.Assert.NotNil(other.Result, "preceding messages must have been applied when calling Apply*; index of first unapplied: %d", i) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This was a genuine bug. |
||
} | ||
m.bc.Assert.True(found, "ApplicableMessage not found") | ||
m.st.ApplyMessage(am) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now you can get accounts and miners separately, each with their own struct containing the relevant data.