-
Notifications
You must be signed in to change notification settings - Fork 324
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[evm] add transaction log for Suicide() #4171
Conversation
@@ -406,6 +412,17 @@ func (stateDB *StateDBAdapter) Suicide(evmAddr common.Address) bool { | |||
stateDB.logError(err) | |||
return false | |||
} | |||
// before calling Suicide, EVM will transfer the contract's balance to beneficiary | |||
// need to create a transaction log on successful suicide | |||
if len(stateDB.lastAddBalanceAmount.Bytes()) > 0 { |
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.
should be check if stateDB.lastAddBalanceAmount != nil && stateDB.lastAddBalanceAmount.Cmp(big.NewInt(0))>0
to prevent nil or negative amount
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.
in AddBalance()
, nil or negative amount will be caught and return error, in other words, lastAddBalanceAmount
must be valid positive number here
add initialization of the value lastAddBalanceAmount
in new
to prevent being nil
@@ -242,6 +245,7 @@ func (stateDB *StateDBAdapter) SubBalance(evmAddr common.Address, amount *big.In | |||
|
|||
// AddBalance adds balance to account | |||
func (stateDB *StateDBAdapter) AddBalance(evmAddr common.Address, amount *big.Int) { | |||
stateDB.lastAddBalanceAmount.SetUint64(0) |
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.
the change is only in AddBalance, does SubBalance
also need it
@@ -242,6 +245,7 @@ func (stateDB *StateDBAdapter) SubBalance(evmAddr common.Address, amount *big.In | |||
|
|||
// AddBalance adds balance to account | |||
func (stateDB *StateDBAdapter) AddBalance(evmAddr common.Address, amount *big.Int) { | |||
stateDB.lastAddBalanceAmount.SetUint64(0) |
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.
what's the purpose?
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.
to clear the amount for each AddBalance(), consider the following:
- AddBalance(4000)
- AddBalance(0)
- Inside Suicide, it calls AddBalance(4000) to beneficiary but failed, if the amount is not cleared, it will mistakenly think the amount match and issue a tx log with amount=4000, but the 4000 is in step 1 and is mistaken
// need to create a transaction log on successful suicide | ||
if len(stateDB.lastAddBalanceAmount.Bytes()) > 0 { | ||
from, _ := address.FromBytes(evmAddr[:]) | ||
stateDB.addTransactionLogs(&action.TransactionLog{ |
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.
if lastAddBalanceAmount is not set or the amount is different from balance, panic?
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.
fixed in latest commit
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.
I think it is not a safe enough way to handle EVM upgrade in the future. If EVM has unexpected calls to AddBalance
and SubBalance
in the future, it would be difficult for us to detect.
Here is my proposal:
-
Basically, operations on
AddBalance
andSubBalance
not triggered byMakeTransfer
are unexpected behaviors in terms of recording transaction logs, and these operations should be append to aUnexpectedOpList
. -
Based on the current logic of the EVM code, when
Suicide
is called, we can remove unexpectedAddBalance
records with the same address and amount from the list, thereby generating a transaction log. -
After the action is executed, we should check the
UnexpectedOpList
. If it is not empty, we should return an error or panic.
good suggestion, will take care in further PRs |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #4171 +/- ##
==========================================
+ Coverage 75.38% 76.18% +0.80%
==========================================
Files 303 340 +37
Lines 25923 29094 +3171
==========================================
+ Hits 19541 22165 +2624
- Misses 5360 5829 +469
- Partials 1022 1100 +78 ☔ View full report in Codecov by Sentry. |
}) | ||
} | ||
} else { | ||
if stateDB.suicideTxLogMismatchPanic { |
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.
for safety, we gate the panic with a flag
after hard-fork, we can run a fullsync w/o the flag, and remove this flag if fullsync pass
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.
https://github.com/iotexproject/iotex-core/pull/4171/files#r1519122441 if we panic here, what's the purpose of resetting the mount?
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.
I gave an example above, if we don't reset the amount, it is possible to generate a mistaken txLog for an earlier AddBalance()
whose amount happens to equal to suicide address
@@ -261,6 +262,7 @@ func WithFeatureCtx(ctx context.Context) context.Context { | |||
SharedGasWithDapp: g.IsToBeEnabled(height), | |||
CandidateRegisterMustWithStake: !g.IsToBeEnabled(height), | |||
DisableDelegateEndorsement: !g.IsToBeEnabled(height), | |||
SuicideTxLogMismatchPanic: g.IsToBeEnabled(height), |
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.
default value should be the value after hard fork
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.
is this a must? to me using a positive (enable after height) flag name will help improve code readability and reduce chance of programming mistake
// before calling Suicide, EVM will transfer the contract's balance to beneficiary | ||
// need to create a transaction log on successful suicide | ||
if stateDB.lastAddBalanceAmount.Cmp(actBalance) == 0 { | ||
if len(stateDB.lastAddBalanceAmount.Bytes()) > 0 { |
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.
ignore efficiency and use stateDB.lastAddBalanceAmount.Cmp(big.NewInt(0)) > 0
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.
updated
}) | ||
} | ||
} else { | ||
if stateDB.suicideTxLogMismatchPanic { |
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.
https://github.com/iotexproject/iotex-core/pull/4171/files#r1519122441 if we panic here, what's the purpose of resetting the mount?
Quality Gate failedFailed conditions |
@@ -48,6 +48,8 @@ type ( | |||
err error | |||
blockHeight uint64 | |||
executionHash hash.Hash256 | |||
lastAddBalanceAddr string |
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.
Retrieving the info from statedb/snapshot ( getStateObject(addr common.Address)
in geth(https://github.com/ethereum/go-ethereum/blob/ebf9e11af2ff701d0961623e817d37b421b96802/core/state/statedb.go#L540) ) seems more reasonable than two new variables under StateDBAdapter for me
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.
can you elaborate? we cannot get the beneficiary's address in StateDBAdapter, so capture it in AddBalance
every time. also we need the transfer amount, not the beneficiary's entire balance
Description
When
Suicide()
is called upon destruction, the contract's balance will be transferred to a beneficiary. This needs to be captured in a transaction logFixes #(issue)
Type of change
Please delete options that are not relevant.
How Has This Been Tested?
Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration
Test Configuration:
Checklist: