mirror of
https://gitlab.com/pulsechaincom/erigon-pulse.git
synced 2024-12-22 19:50:36 +00:00
Fixes in rpctest and rpcdaemon for debug_traceTransaction, and opcode tracer, tool for repairing broken receipts (#2284)
* Fixes in rpctest and rpcdaemon for debug_traceTransaction * Fix for opcode tracer * Tool to fix receipts Co-authored-by: Alexey Sharp <alexeysharp@Alexeys-iMac.local>
This commit is contained in:
parent
95756c8857
commit
f5e42b1e7a
172
cmd/hack/hack.go
172
cmd/hack/hack.go
@ -21,7 +21,13 @@ import (
|
||||
|
||||
"github.com/RoaringBitmap/roaring/roaring64"
|
||||
"github.com/holiman/uint256"
|
||||
"github.com/ledgerwatch/erigon/consensus/ethash"
|
||||
"github.com/ledgerwatch/erigon/consensus/misc"
|
||||
"github.com/ledgerwatch/erigon/core"
|
||||
"github.com/ledgerwatch/erigon/ethdb/cbor"
|
||||
kv2 "github.com/ledgerwatch/erigon/ethdb/kv"
|
||||
"github.com/ledgerwatch/erigon/migrations"
|
||||
"github.com/ledgerwatch/erigon/params"
|
||||
"github.com/wcharczuk/go-chart"
|
||||
"github.com/wcharczuk/go-chart/util"
|
||||
|
||||
@ -37,6 +43,7 @@ import (
|
||||
"github.com/ledgerwatch/erigon/core/state"
|
||||
"github.com/ledgerwatch/erigon/core/types"
|
||||
"github.com/ledgerwatch/erigon/core/types/accounts"
|
||||
"github.com/ledgerwatch/erigon/core/vm"
|
||||
"github.com/ledgerwatch/erigon/eth/stagedsync"
|
||||
"github.com/ledgerwatch/erigon/eth/stagedsync/stages"
|
||||
"github.com/ledgerwatch/erigon/ethdb"
|
||||
@ -2071,26 +2078,121 @@ func scanTxs(chaindata string) error {
|
||||
func scanReceipts(chaindata string, block uint64) error {
|
||||
dbdb := kv2.MustOpen(chaindata).RwKV()
|
||||
defer dbdb.Close()
|
||||
txtx, err := dbdb.BeginRw(context.Background())
|
||||
tx, err := dbdb.BeginRw(context.Background())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer txtx.Rollback()
|
||||
var db ethdb.Database = kv2.WrapIntoTxDB(txtx)
|
||||
var tx ethdb.Tx
|
||||
if hasTx, ok := db.(ethdb.HasTx); ok {
|
||||
tx = hasTx.Tx()
|
||||
} else {
|
||||
return fmt.Errorf("no transaction")
|
||||
}
|
||||
var key [8]byte
|
||||
var v []byte
|
||||
binary.BigEndian.PutUint64(key[:], block)
|
||||
if v, err = tx.GetOne(dbutils.BlockReceiptsPrefix, key[:]); err != nil {
|
||||
defer tx.Rollback()
|
||||
genesisBlock, err := rawdb.ReadBlockByNumber(tx, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("blockNum = %d, receipt %x\n", block, v)
|
||||
return nil
|
||||
chainConfig, cerr := rawdb.ReadChainConfig(tx, genesisBlock.Hash())
|
||||
if cerr != nil {
|
||||
return cerr
|
||||
}
|
||||
vmConfig := vm.Config{}
|
||||
noOpWriter := state.NewNoopWriter()
|
||||
var buf bytes.Buffer
|
||||
fixedCount := 0
|
||||
logInterval := 30 * time.Second
|
||||
logEvery := time.NewTicker(logInterval)
|
||||
for blockNum := block; blockNum < block+100000; blockNum++ {
|
||||
select {
|
||||
default:
|
||||
case <-logEvery.C:
|
||||
log.Info("Commit", "block", blockNum, "fixed", fixedCount)
|
||||
tx.Commit()
|
||||
if tx, err = dbdb.BeginRw(context.Background()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
var hash common.Hash
|
||||
if hash, err = rawdb.ReadCanonicalHash(tx, blockNum); err != nil {
|
||||
return err
|
||||
}
|
||||
if hash == (common.Hash{}) {
|
||||
break
|
||||
}
|
||||
var block *types.Block
|
||||
var senders []common.Address
|
||||
if block, senders, err = rawdb.ReadBlockWithSenders(tx, hash, blockNum); err != nil {
|
||||
return err
|
||||
}
|
||||
receipts := rawdb.ReadReceipts(tx, block, senders)
|
||||
for _, receipt := range receipts {
|
||||
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
|
||||
}
|
||||
if chainConfig.IsByzantium(block.Number().Uint64()) {
|
||||
receiptSha := types.DeriveSha(receipts)
|
||||
if receiptSha == block.Header().ReceiptHash {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
dbstate := state.NewPlainKvState(tx, block.NumberU64()-1)
|
||||
intraBlockState := state.New(dbstate)
|
||||
|
||||
getHeader := func(hash common.Hash, number uint64) *types.Header { return rawdb.ReadHeader(tx, hash, number) }
|
||||
receipts1, err1 := runBlock(intraBlockState, noOpWriter, noOpWriter, chainConfig, getHeader, nil /* checkTEVM */, block, vmConfig)
|
||||
if err1 != nil {
|
||||
return err1
|
||||
}
|
||||
if chainConfig.IsByzantium(block.Number().Uint64()) {
|
||||
receiptSha := types.DeriveSha(receipts1)
|
||||
if receiptSha != block.Header().ReceiptHash {
|
||||
fmt.Printf("(retrace) mismatched receipt headers for block %d: %x, %x\n", block.NumberU64(), receiptSha, block.Header().ReceiptHash)
|
||||
} else {
|
||||
// All good, we can fix receipt record
|
||||
buf.Reset()
|
||||
err := cbor.Marshal(&buf, receipts1)
|
||||
if err != nil {
|
||||
return fmt.Errorf("encode block receipts for block %d: %v", blockNum, err)
|
||||
}
|
||||
if err = tx.Put(dbutils.BlockReceiptsPrefix, dbutils.ReceiptsKey(blockNum), buf.Bytes()); err != nil {
|
||||
return fmt.Errorf("writing receipts for block %d: %v", blockNum, err)
|
||||
}
|
||||
fixedCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func runBlock(ibs *state.IntraBlockState, txnWriter state.StateWriter, blockWriter state.StateWriter,
|
||||
chainConfig *params.ChainConfig, getHeader func(hash common.Hash, number uint64) *types.Header, checkTEVM func(common.Hash) (bool, error), block *types.Block, vmConfig vm.Config) (types.Receipts, error) {
|
||||
header := block.Header()
|
||||
vmConfig.TraceJumpDest = true
|
||||
engine := ethash.NewFullFaker()
|
||||
gp := new(core.GasPool).AddGas(block.GasLimit())
|
||||
usedGas := new(uint64)
|
||||
var receipts types.Receipts
|
||||
if chainConfig.DAOForkSupport && chainConfig.DAOForkBlock != nil && chainConfig.DAOForkBlock.Cmp(block.Number()) == 0 {
|
||||
misc.ApplyDAOHardFork(ibs)
|
||||
}
|
||||
for i, tx := range block.Transactions() {
|
||||
ibs.Prepare(tx.Hash(), block.Hash(), i)
|
||||
receipt, _, err := core.ApplyTransaction(chainConfig, getHeader, engine, nil, gp, ibs, txnWriter, header, tx, usedGas, vmConfig, checkTEVM)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not apply tx %d [%x] failed: %v", i, tx.Hash(), err)
|
||||
}
|
||||
receipts = append(receipts, receipt)
|
||||
//fmt.Printf("%d, cumulative gas: %d\n", i, receipt.CumulativeGasUsed)
|
||||
}
|
||||
|
||||
if !vmConfig.ReadOnly {
|
||||
// Finalize the block, applying any consensus engine specific extras (e.g. block rewards)
|
||||
if _, err := engine.FinalizeAndAssemble(chainConfig, header, ibs, block.Transactions(), block.Uncles(), receipts, nil); err != nil {
|
||||
return nil, fmt.Errorf("finalize of block %d failed: %v", block.NumberU64(), err)
|
||||
}
|
||||
|
||||
ctx := chainConfig.WithEIPsFlags(context.Background(), header.Number.Uint64())
|
||||
if err := ibs.CommitBlock(ctx, blockWriter); err != nil {
|
||||
return nil, fmt.Errorf("committing block %d failed: %v", block.NumberU64(), err)
|
||||
}
|
||||
}
|
||||
|
||||
return receipts, nil
|
||||
}
|
||||
|
||||
var txParseTests = []struct {
|
||||
@ -2139,6 +2241,43 @@ func testTxPool() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
var receiptTests = []struct {
|
||||
cborStr string
|
||||
}{
|
||||
{cborStr: "98a08400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000084004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400000840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000008400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400000840040000184004000018400400001840040000084004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000008400400001840040000184004000018400400001840040000184004000018400400000840040000184004000018400400001840040000184004000008400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001840040000184004000018400400001"},
|
||||
{cborStr: "98a08400f60119e8948400f6011a00028ffb8400f6011a0003777d8400f6011a000a19e18400f6011a000e662c8400f6011a000eb8348400f6011a000f8c3a8400f6011a001040638400f6011a0011374c8400f6011a0011b0d18400f6011a00140bba8400f6011a00145dc28400f6011a00197eab8400f6011a0019d0b38400f6011a001a69898400f6011a001b60728400f6011a001da1118400f6011a001e92a58400f6011a001f5c478400f6011a001fae4f8400f6011a002000578400f6011a0020525f8400f6011a0020a4678400f6011a0020f66f8400f6011a002148778400f6011a00219a7f8400f6011a0021ec878400f6011a00223e8f8400f6011a002290978400f6011a0022e29f8400f6011a00235c248400f6011a0023ae2c8400f6011a002400348400f6011a0024523c8400f6011a0024cbc18400f6011a00251dc98400f6011a00256fd18400f6011a0025c1d98400f6011a0027505d8400f6011a0027a2658400f6011a00282a038400f6011a002be66d8400f6011a003536528400f6011a0035885a8400f6011a0035da628400f6011a0038f4e88400f6011a003946f08400f6011a003b664f8400f6011a003e02188400f6001a003e54208400f6011a004101348400f6011a004417598400f6011a0046439c8400f6011a00470f098400f6011a00479e928400f6011a0047f09a8400f6011a004842a28400f6011a0048f91a8400f6011a00494b228400f6011a00499d2a8400f6011a004a34c88400f6011a004a86d08400f6011a004ad8d88400f6011a004b2ae08400f6011a004d40c38400f6011a004e37ac8400f6011a005220de8400f6011a006680b08400f6011a0068b65f8400f6011a006cada28400f6011a006e77bf8400f6011a007117398400f6011a0071b02a8400f6011a007b8b518400f6011a007c4c088400f6011a007c98b78400f6011a007ceabf8400f6011a0080e8bf8400f6001a008175678400f6011a0081c76f8400f6011a00867d0d8400f6011a0087312a8400f6011a00881e0e8400f6011a008ad2058400f6011a008b86bd8400f6011a008bd8c58400f6011a008c2acd8400f6011a008c7cd58400f6011a008ccedd8400f6011a008d84808400f6011a008dd6888400f6011a008e28908400f6011a008eb8bb8400f6011a00902b2d8400f6011a0091b4508400f6001a0092b8098400f6011a00930a118400f6011a00935c198400f6011a0093ae218400f6011a009400298400f6011a00991f568400f6011a009a97b58400f6011a009ae9bd8400f6011a009b9ed78400f6011a009f69cf8400f6011a00a1364d8400f6011a00a188558400f6011a00a355a28400f6011a00a614ca8400f6011a00a6f05d8400f6011a00a7af5e8400f6011a00aaa96f8400f6011a00acd7898400f6011a00ae6c558400f6011a00b2a59f8400f6011a00b63dc68400f6011a00b8d7bb8400f6001a00b9591b8400f6011a00b9d0528400f6011a00ba22918400f6011a00ba74998400f6001a00baefa68400f6011a00bb41ae8400f6011a00bb93b68400f6011a00bc68e28400f6011a00bcbaea8400f6011a00bd0cf28400f6011a00bd5efa8400f6011a00bdb1028400f6011a00be030a8400f6011a00c1caed8400f6011a00c21cf58400f6011a00c26efd8400f6011a00c2c1058400f6001a00c33c008400f6011a00c3a63b8400f6011a00c585798400f6011a00c70f258400f6011a00c7612d8400f6011a00c98d4c8400f6011a00cb71988400f6001a00cbec998400f6011a00cfe49f8400f6011a00d1c6868400f6011a00d3a86d8400f6011a00d4671a8400f6001a00d4e2f08400f6011a00d6aca68400f6011a00d6feae8400f6011a00d750b68400f6011a00d80d078400f6011a00d85f0f8400f6011a00d915308400f6011a00dbc9d08400f6011a00ddcb408400f6011a00dfad278400f6011a00dfff2f8400f6011a00e272e38400f6011a00e4333c8400f6011a00e4c2c5"},
|
||||
}
|
||||
|
||||
func testReceipts() error {
|
||||
for i, tt := range receiptTests {
|
||||
var cborBytes []byte
|
||||
var err error
|
||||
if cborBytes, err = hex.DecodeString(tt.cborStr); err != nil {
|
||||
return err
|
||||
}
|
||||
var receipts types.Receipts
|
||||
if err := cbor.Unmarshal(&receipts, bytes.NewReader(cborBytes)); err != nil {
|
||||
log.Error("receipt unmarshal failed", "err", err)
|
||||
return nil
|
||||
}
|
||||
fmt.Printf("%d: Number of receipts: %d\n", i, len(receipts))
|
||||
for j, receipt := range receipts {
|
||||
fmt.Printf("%d) type: %d, postState: %x, status: %d, cumulative gas: %d\n", j, receipt.Type, receipt.PostState, receipt.Status, receipt.CumulativeGasUsed)
|
||||
}
|
||||
var oldReceipts migrations.OldReceipts
|
||||
reader := bytes.NewReader(cborBytes)
|
||||
if err = cbor.Unmarshal(&oldReceipts, reader); err != nil {
|
||||
fmt.Printf("Error parsing as old: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf("Unread portion: %d\n", reader.Len())
|
||||
for j, receipt := range oldReceipts {
|
||||
fmt.Printf("old-%d) postState: %x, status: %d, cumulative gas: %d\n", j, receipt.PostState, receipt.Status, receipt.CumulativeGasUsed)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
@ -2301,6 +2440,9 @@ func main() {
|
||||
|
||||
case "testTxPool":
|
||||
err = testTxPool()
|
||||
|
||||
case "testReceipts":
|
||||
err = testReceipts()
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
"github.com/ledgerwatch/erigon/core/state"
|
||||
"github.com/ledgerwatch/erigon/core/types"
|
||||
"github.com/ledgerwatch/erigon/eth/tracers"
|
||||
"github.com/ledgerwatch/erigon/ethdb"
|
||||
"github.com/ledgerwatch/erigon/internal/ethapi"
|
||||
"github.com/ledgerwatch/erigon/rpc"
|
||||
"github.com/ledgerwatch/erigon/turbo/rpchelper"
|
||||
@ -50,8 +49,7 @@ func (api *PrivateDebugAPIImpl) TraceTransaction(ctx context.Context, hash commo
|
||||
getHeader := func(hash common.Hash, number uint64) *types.Header {
|
||||
return rawdb.ReadHeader(tx, hash, number)
|
||||
}
|
||||
checkTEVM := ethdb.GetCheckTEVM(tx)
|
||||
msg, blockCtx, txCtx, ibs, _, err := transactions.ComputeTxEnv(ctx, block, chainConfig, getHeader, checkTEVM, ethash.NewFaker(), tx, blockHash, txIndex)
|
||||
msg, blockCtx, txCtx, ibs, _, err := transactions.ComputeTxEnv(ctx, block, chainConfig, getHeader, nil /* checkTEVM */, ethash.NewFaker(), tx, blockHash, txIndex)
|
||||
if err != nil {
|
||||
stream.WriteNil()
|
||||
return err
|
||||
|
@ -134,18 +134,15 @@ func main() {
|
||||
}
|
||||
with(bench9Cmd, withErigonUrl, withGethUrl, withNeedCompare)
|
||||
|
||||
var bench10Cmd = &cobra.Command{
|
||||
Use: "bench10",
|
||||
var benchTraceTransactionCmd = &cobra.Command{
|
||||
Use: "benchTraceTransaction",
|
||||
Short: "",
|
||||
Long: ``,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := rpctest.Bench10(erigonURL, gethURL, blockFrom, blockTo, recordFile)
|
||||
if err != nil {
|
||||
log.Error("bench 10 err", "err", err)
|
||||
}
|
||||
rpctest.BenchTraceTransaction(erigonURL, gethURL, needCompare, blockFrom, blockTo, recordFile)
|
||||
},
|
||||
}
|
||||
with(bench10Cmd, withGethUrl, withErigonUrl, withBlockNum, withRecord)
|
||||
with(benchTraceTransactionCmd, withGethUrl, withErigonUrl, withNeedCompare, withBlockNum, withRecord)
|
||||
|
||||
var bench11Cmd = &cobra.Command{
|
||||
Use: "bench11",
|
||||
@ -248,7 +245,7 @@ func main() {
|
||||
bench7Cmd,
|
||||
bench8Cmd,
|
||||
bench9Cmd,
|
||||
bench10Cmd,
|
||||
benchTraceTransactionCmd,
|
||||
bench11Cmd,
|
||||
bench12Cmd,
|
||||
bench13Cmd,
|
||||
|
@ -1,63 +0,0 @@
|
||||
package rpctest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Bench10(erigonUrl, gethUrl string, blockFrom uint64, blockTo uint64, recordFile string) error {
|
||||
setRoutes(erigonUrl, gethUrl)
|
||||
var client = &http.Client{
|
||||
Timeout: time.Second * 600,
|
||||
}
|
||||
|
||||
var res CallResult
|
||||
reqGen := &RequestGenerator{
|
||||
client: client,
|
||||
}
|
||||
|
||||
reqGen.reqID++
|
||||
|
||||
for bn := blockFrom; bn < blockTo; bn++ {
|
||||
var b EthBlockByNumber
|
||||
res = reqGen.Erigon("eth_getBlockByNumber", reqGen.getBlockByNumber(bn), &b)
|
||||
if res.Err != nil {
|
||||
return fmt.Errorf("retrieve block (Erigon) %d: %v", blockFrom, res.Err)
|
||||
}
|
||||
if b.Error != nil {
|
||||
return fmt.Errorf("retrieving block (Erigon): %d %s", b.Error.Code, b.Error.Message)
|
||||
}
|
||||
for _, tx := range b.Result.Transactions {
|
||||
reqGen.reqID++
|
||||
|
||||
var trace EthTxTrace
|
||||
res = reqGen.Erigon("debug_traceTransaction", reqGen.traceTransaction(tx.Hash), &trace)
|
||||
if res.Err != nil {
|
||||
fmt.Printf("Could not trace transaction (Erigon) %s: %v\n", tx.Hash, res.Err)
|
||||
print(client, routes[Erigon], reqGen.traceTransaction(tx.Hash))
|
||||
}
|
||||
|
||||
if trace.Error != nil {
|
||||
fmt.Printf("Error tracing transaction (Erigon): %d %s\n", trace.Error.Code, trace.Error.Message)
|
||||
}
|
||||
|
||||
var traceg EthTxTrace
|
||||
res = reqGen.Geth("debug_traceTransaction", reqGen.traceTransaction(tx.Hash), &traceg)
|
||||
if res.Err != nil {
|
||||
print(client, routes[Geth], reqGen.traceTransaction(tx.Hash))
|
||||
return fmt.Errorf("trace transaction (geth) %s: %v", tx.Hash, res.Err)
|
||||
}
|
||||
if traceg.Error != nil {
|
||||
return fmt.Errorf("tracing transaction (geth): %d %s", traceg.Error.Code, traceg.Error.Message)
|
||||
}
|
||||
if res.Err == nil && trace.Error == nil {
|
||||
if !compareTraces(&trace, &traceg) {
|
||||
return fmt.Errorf("different traces block %d, tx %s", blockFrom, tx.Hash)
|
||||
}
|
||||
}
|
||||
reqGen.reqID++
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
87
cmd/rpctest/rpctest/bench_tracetransaction.go
Normal file
87
cmd/rpctest/rpctest/bench_tracetransaction.go
Normal file
@ -0,0 +1,87 @@
|
||||
package rpctest
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func BenchTraceTransaction(erigonUrl, gethUrl string, needCompare bool, blockFrom uint64, blockTo uint64, recordFile string) {
|
||||
setRoutes(erigonUrl, gethUrl)
|
||||
var client = &http.Client{
|
||||
Timeout: time.Second * 600,
|
||||
}
|
||||
|
||||
var rec *bufio.Writer
|
||||
if recordFile != "" {
|
||||
f, err := os.Create(recordFile)
|
||||
if err != nil {
|
||||
fmt.Printf("Cannot create file %s for recording: %v\n", recordFile, err)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
rec = bufio.NewWriter(f)
|
||||
defer rec.Flush()
|
||||
}
|
||||
|
||||
var res CallResult
|
||||
reqGen := &RequestGenerator{
|
||||
client: client,
|
||||
}
|
||||
|
||||
reqGen.reqID++
|
||||
|
||||
for bn := blockFrom; bn < blockTo; bn++ {
|
||||
var b EthBlockByNumber
|
||||
res = reqGen.Erigon("eth_getBlockByNumber", reqGen.getBlockByNumber(bn), &b)
|
||||
if res.Err != nil {
|
||||
fmt.Printf("retrieve block (Erigon) %d: %v", blockFrom, res.Err)
|
||||
return
|
||||
}
|
||||
if b.Error != nil {
|
||||
fmt.Printf("retrieving block (Erigon): %d %s", b.Error.Code, b.Error.Message)
|
||||
return
|
||||
}
|
||||
for _, tx := range b.Result.Transactions {
|
||||
reqGen.reqID++
|
||||
|
||||
request := reqGen.traceTransaction(tx.Hash)
|
||||
recording := rec != nil // This flag will be set to false if recording is not to be performed
|
||||
res = reqGen.Erigon2("debug_traceTransaction", request)
|
||||
|
||||
if res.Err != nil {
|
||||
fmt.Printf("Could not trace transaction (Erigon) %s: %v\n", tx.Hash, res.Err)
|
||||
return
|
||||
}
|
||||
if errVal := res.Result.Get("error"); errVal != nil {
|
||||
fmt.Printf("Error tracing transaction (Erigon): %d %s\n", errVal.GetInt("code"), errVal.GetStringBytes("message"))
|
||||
return
|
||||
}
|
||||
|
||||
if needCompare {
|
||||
resg := reqGen.Geth2("debug_traceTransaction", request)
|
||||
if resg.Err != nil {
|
||||
fmt.Printf("Could not trace transaction (geth) %s: %v\n", tx.Hash, res.Err)
|
||||
return
|
||||
}
|
||||
if errVal := resg.Result.Get("error"); errVal != nil {
|
||||
fmt.Printf("Error tracing transaction (geth): %d %s\n", errVal.GetInt("code"), errVal.GetStringBytes("message"))
|
||||
return
|
||||
}
|
||||
if resg.Err == nil && resg.Result.Get("error") == nil {
|
||||
if err := compareResults(res.Result, resg.Result); err != nil {
|
||||
fmt.Printf("Different traceTransaction block %d, tx %s: %v\n", bn, tx.Hash, err)
|
||||
fmt.Printf("\n\nTG response=================================\n%s\n", res.Response)
|
||||
fmt.Printf("\n\nG response=================================\n%s\n", resg.Response)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if recording {
|
||||
fmt.Fprintf(rec, "%s\n%s\n\n", request, res.Response)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -19,7 +19,6 @@ import (
|
||||
"github.com/ledgerwatch/erigon/core/types"
|
||||
"github.com/ledgerwatch/erigon/core/vm"
|
||||
"github.com/ledgerwatch/erigon/eth/stagedsync/stages"
|
||||
"github.com/ledgerwatch/erigon/ethdb"
|
||||
kv2 "github.com/ledgerwatch/erigon/ethdb/kv"
|
||||
"github.com/ledgerwatch/erigon/log"
|
||||
"github.com/spf13/cobra"
|
||||
@ -137,8 +136,7 @@ func CheckChangeSets(genesis *core.Genesis, blockNum uint64, chaindata string, h
|
||||
}
|
||||
|
||||
getHeader := func(hash common.Hash, number uint64) *types.Header { return rawdb.ReadHeader(rwtx, hash, number) }
|
||||
checkTEVM := ethdb.GetCheckTEVM(rwtx)
|
||||
receipts, err1 := runBlock(intraBlockState, noOpWriter, blockWriter, chainConfig, getHeader, checkTEVM, block, vmConfig)
|
||||
receipts, err1 := runBlock(intraBlockState, noOpWriter, blockWriter, chainConfig, getHeader, nil /* checkTEVM */, block, vmConfig)
|
||||
if err1 != nil {
|
||||
return err1
|
||||
}
|
||||
|
@ -393,10 +393,10 @@ func OpcodeTracer(genesis *core.Genesis, blockNum uint64, chaindata string, numB
|
||||
|
||||
ot := NewOpcodeTracer(blockNum, saveOpcodes, saveBblocks)
|
||||
|
||||
chainDb := kv.MustOpen(chaindata)
|
||||
chainDb := kv.MustOpen(chaindata).RwKV()
|
||||
defer chainDb.Close()
|
||||
historyDb := chainDb
|
||||
historyTx, err1 := historyDb.Begin(context.Background(), ethdb.RO)
|
||||
historyTx, err1 := historyDb.BeginRo(context.Background())
|
||||
if err1 != nil {
|
||||
return err1
|
||||
}
|
||||
@ -526,7 +526,7 @@ func OpcodeTracer(genesis *core.Genesis, blockNum uint64, chaindata string, numB
|
||||
blockNumLastReport := blockNum
|
||||
for !interrupt {
|
||||
var block *types.Block
|
||||
if err := chainDb.RwKV().View(context.Background(), func(tx ethdb.Tx) (err error) {
|
||||
if err := chainDb.View(context.Background(), func(tx ethdb.Tx) (err error) {
|
||||
block, err = rawdb.ReadBlockByNumber(tx, blockNum)
|
||||
return err
|
||||
}); err != nil {
|
||||
@ -544,13 +544,12 @@ func OpcodeTracer(genesis *core.Genesis, blockNum uint64, chaindata string, numB
|
||||
ot.fsumWriter = bufio.NewWriter(fsum)
|
||||
}
|
||||
|
||||
dbstate := state.NewPlainDBState(historyTx, block.NumberU64()-1)
|
||||
dbstate := state.NewPlainKvState(historyTx, block.NumberU64()-1)
|
||||
intraBlockState := state.New(dbstate)
|
||||
intraBlockState.SetTracer(ot)
|
||||
|
||||
getHeader := func(hash common.Hash, number uint64) *types.Header { return rawdb.ReadHeader(chainDb, hash, number) }
|
||||
checkTEVM := ethdb.GetCheckTEVM(chainDb)
|
||||
receipts, err1 := runBlock(intraBlockState, noOpWriter, noOpWriter, chainConfig, getHeader, checkTEVM, block, vmConfig)
|
||||
getHeader := func(hash common.Hash, number uint64) *types.Header { return rawdb.ReadHeader(historyTx, hash, number) }
|
||||
receipts, err1 := runBlock(intraBlockState, noOpWriter, noOpWriter, chainConfig, getHeader, nil /* checkTEVM */, block, vmConfig)
|
||||
if err1 != nil {
|
||||
return err1
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/holiman/uint256"
|
||||
@ -157,8 +158,13 @@ func TraceTx(
|
||||
stream.WriteObjectField("failed")
|
||||
stream.WriteBool(result.Failed())
|
||||
stream.WriteMore()
|
||||
// If the result contains a revert reason, return it.
|
||||
returnVal := fmt.Sprintf("%x", result.Return())
|
||||
if len(result.Revert()) > 0 {
|
||||
returnVal = fmt.Sprintf("%x", result.Revert())
|
||||
}
|
||||
stream.WriteObjectField("returnValue")
|
||||
stream.WriteString(fmt.Sprintf("%x", result.Return()))
|
||||
stream.WriteString(returnVal)
|
||||
stream.WriteObjectEnd()
|
||||
} else {
|
||||
if r, err1 := tracer.(*tracers.Tracer).GetResult(); err1 == nil {
|
||||
@ -181,10 +187,11 @@ type JsonStreamLogger struct {
|
||||
stream *jsoniter.Stream
|
||||
firstCapture bool
|
||||
|
||||
storage map[common.Address]vm.Storage
|
||||
logs []vm.StructLog
|
||||
output []byte //nolint
|
||||
err error //nolint
|
||||
locations common.Hashes // For sorting
|
||||
storage map[common.Address]vm.Storage
|
||||
logs []vm.StructLog
|
||||
output []byte //nolint
|
||||
err error //nolint
|
||||
}
|
||||
|
||||
// NewStructLogger returns a new logger
|
||||
@ -299,14 +306,24 @@ func (l *JsonStreamLogger) CaptureState(env *vm.EVM, pc uint64, op vm.OpCode, ga
|
||||
l.stream.WriteObjectField("storage")
|
||||
l.stream.WriteObjectStart()
|
||||
first := true
|
||||
for i, storageValue := range l.storage[contract.Address()] {
|
||||
// Sort storage by locations for easier comparison with geth
|
||||
if l.locations != nil {
|
||||
l.locations = l.locations[:0]
|
||||
}
|
||||
s := l.storage[contract.Address()]
|
||||
for loc := range s {
|
||||
l.locations = append(l.locations, loc)
|
||||
}
|
||||
sort.Sort(l.locations)
|
||||
for _, loc := range l.locations {
|
||||
value := s[loc]
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
l.stream.WriteMore()
|
||||
}
|
||||
l.stream.WriteObjectField(fmt.Sprintf("%x", i))
|
||||
l.stream.WriteString(fmt.Sprintf("%x", storageValue))
|
||||
l.stream.WriteObjectField(fmt.Sprintf("%x", loc))
|
||||
l.stream.WriteString(fmt.Sprintf("%x", value))
|
||||
}
|
||||
l.stream.WriteObjectEnd()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user