2018-06-19 11:32:26 +00:00
|
|
|
// Code copied from go-ethereum
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2018-07-02 22:28:39 +00:00
|
|
|
"fmt"
|
2018-06-19 11:32:26 +00:00
|
|
|
"math/big"
|
|
|
|
|
2018-07-02 22:28:39 +00:00
|
|
|
"github.com/ethereum/go-ethereum/common/math"
|
2018-07-04 23:38:20 +00:00
|
|
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
2018-06-19 11:32:26 +00:00
|
|
|
"github.com/ethereum/go-ethereum/core/state"
|
|
|
|
"github.com/ethereum/go-ethereum/core/types"
|
2018-07-02 22:28:39 +00:00
|
|
|
"github.com/ethereum/go-ethereum/core/vm"
|
2018-06-19 11:32:26 +00:00
|
|
|
"github.com/ethereum/go-ethereum/params"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Some weird constants to avoid constant memory allocs for them.
|
|
|
|
var (
|
|
|
|
big8 = big.NewInt(8)
|
|
|
|
big32 = big.NewInt(32)
|
|
|
|
)
|
|
|
|
|
|
|
|
// AccumulateRewards credits the coinbase of the given block with the mining
|
|
|
|
// reward. The total reward consists of the static block reward and rewards for
|
|
|
|
// included uncles. The coinbase of each uncle block is also rewarded.
|
|
|
|
func accumulateRewards(config *params.ChainConfig, state *state.StateDB, header *types.Header, uncles []*types.Header) {
|
|
|
|
// Select the correct block reward based on chain progression
|
|
|
|
blockReward := ethash.FrontierBlockReward
|
|
|
|
if config.IsByzantium(header.Number) {
|
|
|
|
blockReward = ethash.ByzantiumBlockReward
|
|
|
|
}
|
|
|
|
// Accumulate the rewards for the miner and any included uncles
|
|
|
|
reward := new(big.Int).Set(blockReward)
|
|
|
|
r := new(big.Int)
|
|
|
|
for _, uncle := range uncles {
|
|
|
|
r.Add(uncle.Number, big8)
|
|
|
|
r.Sub(r, header.Number)
|
|
|
|
r.Mul(r, blockReward)
|
|
|
|
r.Div(r, big8)
|
|
|
|
state.AddBalance(uncle.Coinbase, r)
|
|
|
|
|
|
|
|
r.Div(blockReward, big32)
|
|
|
|
reward.Add(reward, r)
|
|
|
|
}
|
|
|
|
state.AddBalance(header.Coinbase, reward)
|
|
|
|
}
|
2018-07-02 22:28:39 +00:00
|
|
|
|
|
|
|
// StructLogRes stores a structured log emitted by the EVM while replaying a
|
|
|
|
// transaction in debug mode
|
|
|
|
type StructLogRes struct {
|
|
|
|
Pc uint64 `json:"pc"`
|
|
|
|
Op string `json:"op"`
|
|
|
|
Gas uint64 `json:"gas"`
|
|
|
|
GasCost uint64 `json:"gasCost"`
|
|
|
|
Depth int `json:"depth"`
|
|
|
|
Error error `json:"error,omitempty"`
|
|
|
|
Stack *[]string `json:"stack,omitempty"`
|
|
|
|
Memory *[]string `json:"memory,omitempty"`
|
|
|
|
Storage *map[string]string `json:"storage,omitempty"`
|
|
|
|
}
|
|
|
|
|
2018-07-04 23:38:20 +00:00
|
|
|
// formatLogs formats EVM returned structured logs for json output
|
2018-07-02 22:28:39 +00:00
|
|
|
func FormatLogs(logs []vm.StructLog) []StructLogRes {
|
|
|
|
formatted := make([]StructLogRes, len(logs))
|
|
|
|
for index, trace := range logs {
|
|
|
|
formatted[index] = StructLogRes{
|
|
|
|
Pc: trace.Pc,
|
|
|
|
Op: trace.Op.String(),
|
|
|
|
Gas: trace.Gas,
|
|
|
|
GasCost: trace.GasCost,
|
|
|
|
Depth: trace.Depth,
|
|
|
|
Error: trace.Err,
|
|
|
|
}
|
|
|
|
if trace.Stack != nil {
|
|
|
|
stack := make([]string, len(trace.Stack))
|
|
|
|
for i, stackValue := range trace.Stack {
|
|
|
|
stack[i] = fmt.Sprintf("%x", math.PaddedBigBytes(stackValue, 32))
|
|
|
|
}
|
|
|
|
formatted[index].Stack = &stack
|
|
|
|
}
|
|
|
|
if trace.Memory != nil {
|
|
|
|
memory := make([]string, 0, (len(trace.Memory)+31)/32)
|
|
|
|
for i := 0; i+32 <= len(trace.Memory); i += 32 {
|
|
|
|
memory = append(memory, fmt.Sprintf("%x", trace.Memory[i:i+32]))
|
|
|
|
}
|
|
|
|
formatted[index].Memory = &memory
|
|
|
|
}
|
|
|
|
if trace.Storage != nil {
|
|
|
|
storage := make(map[string]string)
|
|
|
|
for i, storageValue := range trace.Storage {
|
|
|
|
storage[fmt.Sprintf("%x", i)] = fmt.Sprintf("%x", storageValue)
|
|
|
|
}
|
|
|
|
formatted[index].Storage = &storage
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return formatted
|
|
|
|
}
|