executedCode fixes

This commit is contained in:
Arun Dhyani 2024-01-16 16:10:04 +08:00
parent 8545daf9f9
commit 0ed6e530ac

View file

@ -64,6 +64,7 @@ type Firehose struct {
blockFinality *FinalityStatus blockFinality *FinalityStatus
// Transaction state // Transaction state
evm *vm.EVM
transaction *pbeth.TransactionTrace transaction *pbeth.TransactionTrace
transactionLogIndex uint32 transactionLogIndex uint32
isPrecompiledAddr func(addr common.Address) bool isPrecompiledAddr func(addr common.Address) bool
@ -109,6 +110,7 @@ func (f *Firehose) resetBlock() {
// resetTransaction resets the transaction state and the call state in one shot // resetTransaction resets the transaction state and the call state in one shot
func (f *Firehose) resetTransaction() { func (f *Firehose) resetTransaction() {
f.transaction = nil f.transaction = nil
f.evm = nil
f.transactionLogIndex = 0 f.transactionLogIndex = 0
f.isPrecompiledAddr = nil f.isPrecompiledAddr = nil
@ -175,6 +177,7 @@ func (f *Firehose) CaptureTxStart(evm *vm.EVM, tx *types.Transaction, from commo
f.ensureInBlockAndNotInTrxAndNotInCall() f.ensureInBlockAndNotInTrxAndNotInCall()
f.evm = evm
var to common.Address var to common.Address
if tx.To() == nil { if tx.To() == nil {
to = crypto.CreateAddress(from, evm.StateDB.GetNonce(from)) to = crypto.CreateAddress(from, evm.StateDB.GetNonce(from))
@ -409,9 +412,11 @@ func (f *Firehose) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope
} }
func (f *Firehose) captureInterpreterStep(activeCall *pbeth.Call, pc uint64, op vm.OpCode, gas, cost uint64, _ *vm.ScopeContext, rData []byte, depth int, err error) { func (f *Firehose) captureInterpreterStep(activeCall *pbeth.Call, pc uint64, op vm.OpCode, gas, cost uint64, _ *vm.ScopeContext, rData []byte, depth int, err error) {
if !activeCall.ExecutedCode { // for call, we need to process the executed code here
firehoseTrace("setting active call executed code to true") // since in old firehose executed code calculation depends if the code exist
activeCall.ExecutedCode = true if activeCall.CallType == pbeth.CallType_CALL && !activeCall.ExecutedCode {
firehoseTrace("Intepreter step for callType_CALL")
activeCall.ExecutedCode = len(activeCall.Input) > 0
} }
} }
@ -470,6 +475,9 @@ func (f *Firehose) callStart(source string, callType pbeth.CallType, from common
GasLimit: gas, GasLimit: gas,
} }
precompile := f.isPrecompiledAddr(common.BytesToAddress(call.Address))
call.ExecutedCode = getExecutedCode(f.evm, precompile, call)
// Known Firehose issue: The BeginOrdinal of the genesis block root call is never actually // Known Firehose issue: The BeginOrdinal of the genesis block root call is never actually
// incremented and it's always 0. // incremented and it's always 0.
// //
@ -496,6 +504,31 @@ func (f *Firehose) callStart(source string, callType pbeth.CallType, from common
f.callStack.Push(call) f.callStack.Push(call)
} }
func getExecutedCode(evm *vm.EVM, precompile bool, call *pbeth.Call) bool {
if evm != nil && call.CallType == pbeth.CallType_CALL {
if !evm.StateDB.Exist(common.BytesToAddress(call.Address)) &&
!precompile && evm.ChainConfig().Rules(evm.Context.BlockNumber, evm.Context.Random != nil, evm.Context.Time).IsEIP158 &&
(call.Value == nil || call.Value.Native().Sign() == 0) {
firehoseDebug("executed code IsSpuriousDragon callTyp=%s inputLength=%d", call.CallType.String(), len(call.Input) > 0)
return call.CallType != pbeth.CallType_CREATE && len(call.Input) > 0
}
}
if precompile {
firehoseDebug("executed code isprecompile callTyp=%s inputLength=%d", call.CallType.String(), len(call.Input) > 0)
return call.CallType != pbeth.CallType_CREATE && len(call.Input) > 0
}
if call.CallType == pbeth.CallType_CALL {
firehoseDebug("executed code callType_CALL")
// calculation for executed code will happen in captureInterpreterStep
return false
}
firehoseDebug("executed code default callTyp=%s inputLength=%d", call.CallType.String(), len(call.Input) > 0)
return call.CallType != pbeth.CallType_CREATE && len(call.Input) > 0
}
func (f *Firehose) callEnd(source string, output []byte, gasUsed uint64, err error, reverted bool) { func (f *Firehose) callEnd(source string, output []byte, gasUsed uint64, err error, reverted bool) {
firehoseDebug("call end source=%s index=%d output=%s gasUsed=%d err=%s reverted=%t", source, f.callStack.ActiveIndex(), outputView(output), gasUsed, errorView(err), reverted) firehoseDebug("call end source=%s index=%d output=%s gasUsed=%d err=%s reverted=%t", source, f.callStack.ActiveIndex(), outputView(output), gasUsed, errorView(err), reverted)
@ -537,19 +570,19 @@ func (f *Firehose) callEnd(source string, output []byte, gasUsed uint64, err err
// to false // to false
// //
// For precompiled address however, interpreter does not run so determine there was a bug in Firehose instrumentation where we would // For precompiled address however, interpreter does not run so determine there was a bug in Firehose instrumentation where we would
if call.ExecutedCode || f.isPrecompiledAddr(common.BytesToAddress(call.Address)) { // if call.ExecutedCode || f.isPrecompiledAddr(common.BytesToAddress(call.Address)) {
// In this case, we are sure that some code executed. This translates in the old Firehose instrumentation // // In this case, we are sure that some code executed. This translates in the old Firehose instrumentation
// that it would have **never** emitted an `account_without_code`. // // that it would have **never** emitted an `account_without_code`.
// // //
// When no `account_without_code` was executed in the previous Firehose instrumentation, // // When no `account_without_code` was executed in the previous Firehose instrumentation,
// the `call.ExecutedCode` defaulted to the condition below // // the `call.ExecutedCode` defaulted to the condition below
call.ExecutedCode = call.CallType != pbeth.CallType_CREATE && len(call.Input) > 0 // call.ExecutedCode = call.CallType != pbeth.CallType_CREATE && len(call.Input) > 0
} else { // } else {
// In all other cases, we are sure that no code executed. This translates in the old Firehose instrumentation // // In all other cases, we are sure that no code executed. This translates in the old Firehose instrumentation
// that it would have emitted an `account_without_code` and it would have then forced set the `call.ExecutedCode` // // that it would have emitted an `account_without_code` and it would have then forced set the `call.ExecutedCode`
// to `false`. // // to `false`.
call.ExecutedCode = false // call.ExecutedCode = false
} // }
if reverted { if reverted {
failureReason := "" failureReason := ""