Patch for concurrent iterator & others (onto v1.11.6) #386

Closed
roysc wants to merge 1565 commits from v1.11.6-statediff-v5 into master
12 changed files with 4226 additions and 1 deletions
Showing only changes of commit 8e69622c68 - Show all commits

View File

@ -46,6 +46,13 @@ type callContext struct {
Miner common.Address `json:"miner"` Miner common.Address `json:"miner"`
} }
// callLog is the result of LOG opCode
type callLog struct {
Address common.Address `json:"address"`
Topics []common.Hash `json:"topics"`
Data hexutil.Bytes `json:"data"`
}
// callTrace is the result of a callTracer run. // callTrace is the result of a callTracer run.
type callTrace struct { type callTrace struct {
From common.Address `json:"from"` From common.Address `json:"from"`
@ -57,6 +64,7 @@ type callTrace struct {
Error string `json:"error,omitempty"` Error string `json:"error,omitempty"`
Revertal string `json:"revertReason,omitempty"` Revertal string `json:"revertReason,omitempty"`
Calls []callTrace `json:"calls,omitempty"` Calls []callTrace `json:"calls,omitempty"`
Logs []callLog `json:"logs,omitempty"`
Value *hexutil.Big `json:"value,omitempty"` Value *hexutil.Big `json:"value,omitempty"`
// Gencodec adds overridden fields at the end // Gencodec adds overridden fields at the end
Type string `json:"type"` Type string `json:"type"`
@ -81,6 +89,10 @@ func TestCallTracerNative(t *testing.T) {
testCallTracer("callTracer", "call_tracer", t) testCallTracer("callTracer", "call_tracer", t)
} }
func TestCallTracerNativeWithLog(t *testing.T) {
testCallTracer("callTracer", "call_tracer_withLog", t)
}
func testCallTracer(tracerName string, dirPath string, t *testing.T) { func testCallTracer(tracerName string, dirPath string, t *testing.T) {
isLegacy := strings.HasSuffix(dirPath, "_legacy") isLegacy := strings.HasSuffix(dirPath, "_legacy")
files, err := os.ReadDir(filepath.Join("testdata", dirPath)) files, err := os.ReadDir(filepath.Join("testdata", dirPath))

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,84 @@
{
"genesis": {
"difficulty": "8430028481555",
"extraData": "0xd783010302844765746887676f312e352e31856c696e7578",
"gasLimit": "3141592",
"hash": "0xde66937783697293f2e529d2034887c531535d78afa8c9051511ae12ba48fbea",
"miner": "0x2a65aca4d5fc5b5c859090a6c34d164135398226",
"mixHash": "0xba28a43bfbca4a2effbb76bb70d03482a8a0c92e2883ff36cbac3d7c6dbb7df5",
"nonce": "0xa3827ec0a82fe823",
"number": "765824",
"stateRoot": "0x8d96cb027a29f8ca0ccd6d31f9ea0656136ec8030ecda70bb9231849ed6f41a2",
"timestamp": "1451389443",
"totalDifficulty": "4838314986494741271",
"alloc": {
"0xd1220a0cf47c7b9be7a2e6ba89f429762e7b9adb": {
"balance": "0x14203bee2ea6fbe8c",
"nonce": "34"
},
"0xe2fe6b13287f28e193333fdfe7fedf2f6df6124a": {
"balance": "0x2717a9c870a286f4350"
},
"0xf4eced2f682ce333f96f2d8966c613ded8fc95dd": {
"balance": "0x0",
"code": "0x606060405260e060020a600035046306fdde038114610047578063313ce567146100a457806370a08231146100b057806395d89b41146100c8578063a9059cbb14610123575b005b61015260008054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156101f55780601f106101ca576101008083540402835291602001916101f5565b6101c060025460ff1681565b6101c060043560036020526000908152604090205481565b610152600180546020601f6002600019610100858716150201909316929092049182018190040260809081016040526060828152929190828280156101f55780601f106101ca576101008083540402835291602001916101f5565b610045600435602435600160a060020a033316600090815260036020526040902054819010156101fd57610002565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600302600f01f150905090810190601f1680156101b25780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6060908152602090f35b820191906000526020600020905b8154815290600101906020018083116101d857829003601f168201915b505050505081565b600160a060020a03821660009081526040902054808201101561021f57610002565b806003600050600033600160a060020a03168152602001908152602001600020600082828250540392505081905550806003600050600084600160a060020a0316815260200190815260200160002060008282825054019250508190555081600160a060020a031633600160a060020a03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505056",
"storage": {
"0x1dae8253445d3a5edbe8200da9fc39bc4f11db9362181dc1b640d08c3c2fb4d6": "0x0000000000000000000000000000000000000000000000000000000000000000",
"0x8ba52aac7f255d80a49abcf003d6af4752aba5a9531cae94fde7ac8d72191d67": "0x000000000000000000000000000000000000000000000000000000000178e460"
}
}
},
"config": {
"chainId": 1,
"homesteadBlock": 1150000,
"daoForkBlock": 1920000,
"daoForkSupport": true,
"eip150Block": 2463000,
"eip150Hash": "0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0",
"eip155Block": 2675000,
"eip158Block": 2675000,
"byzantiumBlock": 4370000,
"constantinopleBlock": 7280000,
"petersburgBlock": 7280000,
"istanbulBlock": 9069000,
"muirGlacierBlock": 9200000,
"berlinBlock": 12244000,
"londonBlock": 12965000,
"arrowGlacierBlock": 13773000,
"grayGlacierBlock": 15050000,
"terminalTotalDifficultyPassed": true,
"ethash": {}
}
},
"context": {
"number": "765825",
"difficulty": "8425912256743",
"timestamp": "1451389488",
"gasLimit": "3141592",
"miner": "0xe2fe6b13287f28e193333fdfe7fedf2f6df6124a"
},
"input": "0xf8aa22850ba43b740083024d4594f4eced2f682ce333f96f2d8966c613ded8fc95dd80b844a9059cbb000000000000000000000000dbf03b407c01e7cd3cbea99509d93f8dddc8c6fb00000000000000000000000000000000000000000000000000000000009896801ca067da548a2e0f381a957b9b51f086073375d6bfc7312cbc9540b3647ccab7db11a042c6e5b34bc7ba821e9c25b166fa13d82ad4b0d044d16174d5587d4f04ecfcd1",
"tracerConfig": {
"withLog": true
},
"result": {
"from": "0xd1220a0cf47c7b9be7a2e6ba89f429762e7b9adb",
"gas": "0x1f36d",
"gasUsed": "0xc6a5",
"to": "0xf4eced2f682ce333f96f2d8966c613ded8fc95dd",
"input": "0xa9059cbb000000000000000000000000dbf03b407c01e7cd3cbea99509d93f8dddc8c6fb0000000000000000000000000000000000000000000000000000000000989680",
"logs": [
{
"address": "0xf4eced2f682ce333f96f2d8966c613ded8fc95dd",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x000000000000000000000000d1220a0cf47c7b9be7a2e6ba89f429762e7b9adb",
"0x000000000000000000000000dbf03b407c01e7cd3cbea99509d93f8dddc8c6fb"
],
"data": "0x0000000000000000000000000000000000000000000000000000000000989680"
}
],
"value": "0x0",
"type": "CALL"
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -36,6 +36,12 @@ func init() {
register("callTracer", newCallTracer) register("callTracer", newCallTracer)
} }
type callLog struct {
Address common.Address `json:"address"`
Topics []common.Hash `json:"topics"`
Data hexutil.Bytes `json:"data"`
}
type callFrame struct { type callFrame struct {
Type vm.OpCode `json:"-"` Type vm.OpCode `json:"-"`
From common.Address `json:"from"` From common.Address `json:"from"`
@ -47,6 +53,7 @@ type callFrame struct {
Error string `json:"error,omitempty" rlp:"optional"` Error string `json:"error,omitempty" rlp:"optional"`
Revertal string `json:"revertReason,omitempty"` Revertal string `json:"revertReason,omitempty"`
Calls []callFrame `json:"calls,omitempty" rlp:"optional"` Calls []callFrame `json:"calls,omitempty" rlp:"optional"`
Logs []callLog `json:"logs,omitempty" rlp:"optional"`
// Placed at end on purpose. The RLP will be decoded to 0 instead of // Placed at end on purpose. The RLP will be decoded to 0 instead of
// nil if there are non-empty elements after in the struct. // nil if there are non-empty elements after in the struct.
Value *big.Int `json:"value,omitempty" rlp:"optional"` Value *big.Int `json:"value,omitempty" rlp:"optional"`
@ -56,6 +63,10 @@ func (f callFrame) TypeString() string {
return f.Type.String() return f.Type.String()
} }
func (f callFrame) failed() bool {
return len(f.Error) > 0
}
func (f *callFrame) capture(output []byte, err error) { func (f *callFrame) capture(output []byte, err error) {
output = common.CopyBytes(output) output = common.CopyBytes(output)
if err == nil { if err == nil {
@ -98,6 +109,7 @@ type callTracer struct {
type callTracerConfig struct { type callTracerConfig struct {
OnlyTopCall bool `json:"onlyTopCall"` // If true, call tracer won't collect any subcalls OnlyTopCall bool `json:"onlyTopCall"` // If true, call tracer won't collect any subcalls
WithLog bool `json:"withLog"` // If true, call tracer will collect event logs
} }
// newCallTracer returns a native go tracer which tracks // newCallTracer returns a native go tracer which tracks
@ -137,10 +149,38 @@ func (t *callTracer) CaptureEnd(output []byte, gasUsed uint64, _ time.Duration,
// CaptureState implements the EVMLogger interface to trace a single step of VM execution. // CaptureState implements the EVMLogger interface to trace a single step of VM execution.
func (t *callTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) { func (t *callTracer) CaptureState(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, rData []byte, depth int, err error) {
// Only logs need to be captured via opcode processing
if !t.config.WithLog {
return
}
// Avoid processing nested calls when only caring about top call
if t.config.OnlyTopCall && depth > 0 {
return
}
switch op {
case vm.LOG0, vm.LOG1, vm.LOG2, vm.LOG3, vm.LOG4:
size := int(op - vm.LOG0)
stack := scope.Stack
stackData := stack.Data()
// Don't modify the stack
mStart := stackData[len(stackData)-1]
mSize := stackData[len(stackData)-2]
topics := make([]common.Hash, size)
for i := 0; i < size; i++ {
topic := stackData[len(stackData)-2-(i+1)]
topics[i] = common.Hash(topic.Bytes32())
}
data := scope.Memory.GetCopy(int64(mStart.Uint64()), int64(mSize.Uint64()))
log := callLog{Address: scope.Contract.Address(), Topics: topics, Data: hexutil.Bytes(data)}
t.callstack[len(t.callstack)-1].Logs = append(t.callstack[len(t.callstack)-1].Logs, log)
}
} }
// CaptureFault implements the EVMLogger interface to trace an execution fault. // CaptureFault implements the EVMLogger interface to trace an execution fault.
func (t *callTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, _ *vm.ScopeContext, depth int, err error) { func (t *callTracer) CaptureFault(pc uint64, op vm.OpCode, gas, cost uint64, scope *vm.ScopeContext, depth int, err error) {
} }
// CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct). // CaptureEnter is called when EVM enters a new scope (via call, create or selfdestruct).
@ -191,6 +231,10 @@ func (t *callTracer) CaptureTxStart(gasLimit uint64) {
func (t *callTracer) CaptureTxEnd(restGas uint64) { func (t *callTracer) CaptureTxEnd(restGas uint64) {
t.callstack[0].GasUsed = t.gasLimit - restGas t.callstack[0].GasUsed = t.gasLimit - restGas
if t.config.WithLog {
// Logs are not emitted when the call fails
clearFailedLogs(&t.callstack[0], false)
}
} }
// GetResult returns the json-encoded nested list of call traces, and any // GetResult returns the json-encoded nested list of call traces, and any
@ -211,3 +255,16 @@ func (t *callTracer) Stop(err error) {
t.reason = err t.reason = err
atomic.StoreUint32(&t.interrupt, 1) atomic.StoreUint32(&t.interrupt, 1)
} }
// clearFailedLogs clears the logs of a callframe and all its children
// in case of execution failure.
func clearFailedLogs(cf *callFrame, parentFailed bool) {
failed := cf.failed() || parentFailed
// Clear own logs
if failed {
cf.Logs = nil
}
for i := range cf.Calls {
clearFailedLogs(&cf.Calls[i], failed)
}
}

View File

@ -26,6 +26,7 @@ func (c callFrame) MarshalJSON() ([]byte, error) {
Error string `json:"error,omitempty" rlp:"optional"` Error string `json:"error,omitempty" rlp:"optional"`
Revertal string `json:"revertReason,omitempty"` Revertal string `json:"revertReason,omitempty"`
Calls []callFrame `json:"calls,omitempty" rlp:"optional"` Calls []callFrame `json:"calls,omitempty" rlp:"optional"`
Logs []callLog `json:"logs,omitempty" rlp:"optional"`
Value *hexutil.Big `json:"value,omitempty" rlp:"optional"` Value *hexutil.Big `json:"value,omitempty" rlp:"optional"`
TypeString string `json:"type"` TypeString string `json:"type"`
} }
@ -40,6 +41,7 @@ func (c callFrame) MarshalJSON() ([]byte, error) {
enc.Error = c.Error enc.Error = c.Error
enc.Revertal = c.Revertal enc.Revertal = c.Revertal
enc.Calls = c.Calls enc.Calls = c.Calls
enc.Logs = c.Logs
enc.Value = (*hexutil.Big)(c.Value) enc.Value = (*hexutil.Big)(c.Value)
enc.TypeString = c.TypeString() enc.TypeString = c.TypeString()
return json.Marshal(&enc) return json.Marshal(&enc)
@ -58,6 +60,7 @@ func (c *callFrame) UnmarshalJSON(input []byte) error {
Error *string `json:"error,omitempty" rlp:"optional"` Error *string `json:"error,omitempty" rlp:"optional"`
Revertal *string `json:"revertReason,omitempty"` Revertal *string `json:"revertReason,omitempty"`
Calls []callFrame `json:"calls,omitempty" rlp:"optional"` Calls []callFrame `json:"calls,omitempty" rlp:"optional"`
Logs []callLog `json:"logs,omitempty" rlp:"optional"`
Value *hexutil.Big `json:"value,omitempty" rlp:"optional"` Value *hexutil.Big `json:"value,omitempty" rlp:"optional"`
} }
var dec callFrame0 var dec callFrame0
@ -94,6 +97,9 @@ func (c *callFrame) UnmarshalJSON(input []byte) error {
if dec.Calls != nil { if dec.Calls != nil {
c.Calls = dec.Calls c.Calls = dec.Calls
} }
if dec.Logs != nil {
c.Logs = dec.Logs
}
if dec.Value != nil { if dec.Value != nil {
c.Value = (*big.Int)(dec.Value) c.Value = (*big.Int)(dec.Value)
} }