erigon-pulse/cmd/rpctest/main.go
ledgerwatch 0c6a44b5e5
Index bits to mark creation of accounts or storage items (#483)
* Index bits

* Fix linter

* Fix linter

* Not to call getModifiedAccountsByNumber for go-ethereum

* Remove the 0x000 kludge
2020-04-25 15:50:32 +01:00

1568 lines
48 KiB
Go

package main
import (
"bufio"
"bytes"
"encoding/base64"
"encoding/json"
"flag"
"fmt"
"io"
"net/http"
"os"
"path"
"strings"
"time"
"github.com/ledgerwatch/turbo-geth/common"
"github.com/ledgerwatch/turbo-geth/common/hexutil"
"github.com/ledgerwatch/turbo-geth/core/state"
"github.com/ledgerwatch/turbo-geth/crypto"
"github.com/ledgerwatch/turbo-geth/log"
"github.com/mattn/go-colorable"
"github.com/mattn/go-isatty"
)
var action = flag.String("action", "", "action to execute")
var url = flag.String("url", "", "URL to use for RPC requests")
var block = flag.Int("block", 1, "specifies a block number for operation")
var chaindata = flag.String("chaindata", "chaindata", "path to the chaindata database file")
type EthError struct {
Code int `json:"code"`
Message string `json:"message"`
}
type CommonResponse struct {
Version string `json:"jsonrpc"`
RequestId int `json:"id"`
Error *EthError `json:"error"`
}
type EthBlockNumber struct {
CommonResponse
Number hexutil.Uint64 `json:"result"`
}
type EthBalance struct {
CommonResponse
Balance hexutil.Big `json:"result"`
}
type EthTransaction struct {
From common.Address `json:"from"`
To *common.Address `json:"to"` // Pointer because it might be missing
Hash string `json:"hash"`
Gas hexutil.Big `json:"gas"`
}
type EthBlockByNumberResult struct {
Difficulty hexutil.Big `json:"difficulty"`
Miner common.Address `json:"miner"`
Transactions []EthTransaction `json:"transactions"`
TxRoot common.Hash `json:"transactionsRoot"`
Hash common.Hash `json:"hash"`
}
type EthBlockByNumber struct {
CommonResponse
Result EthBlockByNumberResult `json:"result"`
}
type StructLog struct {
Op string `json:"op"`
Pc uint64 `json:"pc"`
Depth uint64 `json:"depth"`
Error *EthError `json:"error"`
Gas uint64 `json:"gas"`
GasCost uint64 `json:"gasCost"`
Memory []string `json:"memory"`
Stack []string `json:"stack"`
Storage map[string]string `json:"storage"`
}
type EthTxTraceResult struct {
Gas uint64 `json:"gas"`
Failed bool `json:"failed"`
ReturnValue string `json:"returnValue"`
StructLogs []StructLog `json:"structLogs"`
}
type EthTxTrace struct {
CommonResponse
Result EthTxTraceResult `json:"result"`
}
type DebugModifiedAccounts struct {
CommonResponse
Result []common.Address `json:"result"`
}
// StorageRangeResult is the result of a debug_storageRangeAt API call.
type StorageRangeResult struct {
Storage storageMap `json:"storage"`
NextKey *common.Hash `json:"nextKey"` // nil if Storage includes the last key in the trie.
}
type storageMap map[common.Hash]storageEntry
type storageEntry struct {
Key *common.Hash `json:"key"`
Value common.Hash `json:"value"`
}
type DebugStorageRange struct {
CommonResponse
Result StorageRangeResult `json:"result"`
}
type DebugAccountRange struct {
CommonResponse
Result state.IteratorDump `json:"result"`
}
// Log represents a contract log event. These events are generated by the LOG opcode and
// stored/indexed by the node.
type Log struct {
// Consensus fields:
// address of the contract that generated the event
Address common.Address `json:"address" gencodec:"required"`
// list of topics provided by the contract.
Topics []common.Hash `json:"topics" gencodec:"required"`
// supplied by the contract, usually ABI-encoded
Data hexutil.Bytes `json:"data" gencodec:"required"`
// Derived fields. These fields are filled in by the node
// but not secured by consensus.
// block in which the transaction was included
BlockNumber hexutil.Uint64 `json:"blockNumber"`
// hash of the transaction
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
// index of the transaction in the block
TxIndex hexutil.Uint `json:"transactionIndex" gencodec:"required"`
// hash of the block in which the transaction was included
BlockHash common.Hash `json:"blockHash"`
// index of the log in the receipt
Index hexutil.Uint `json:"logIndex" gencodec:"required"`
// The Removed field is true if this log was reverted due to a chain reorganisation.
// You must pay attention to this field if you receive logs through a filter query.
Removed bool `json:"removed"`
}
type Receipt struct {
// Consensus fields
PostState common.Hash `json:"root"`
Status hexutil.Uint64 `json:"status"`
CumulativeGasUsed hexutil.Uint64 `json:"cumulativeGasUsed" gencodec:"required"`
Bloom hexutil.Bytes `json:"logsBloom" gencodec:"required"`
Logs []*Log `json:"logs" gencodec:"required"`
// Implementation fields (don't reorder!)
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
ContractAddress *common.Address `json:"contractAddress"`
GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
}
type EthReceipt struct {
CommonResponse
Result Receipt `json:"result"`
}
type EthLogs struct {
CommonResponse
Result []*Log `json:"result"`
}
func post(client *http.Client, url, request string, response interface{}) error {
log.Info("Getting", "url", url, "request", request)
start := time.Now()
r, err := client.Post(url, "application/json", strings.NewReader(request))
if err != nil {
return err
}
defer r.Body.Close()
if r.StatusCode != 200 {
return fmt.Errorf("status %s", r.Status)
}
decoder := json.NewDecoder(r.Body)
err = decoder.Decode(response)
log.Info("Got in", "time", time.Since(start).Seconds())
return err
}
func print(client *http.Client, url, request string) {
r, err := client.Post(url, "application/json", strings.NewReader(request))
if err != nil {
fmt.Printf("Could not print: %v\n", err)
return
}
if r.StatusCode != 200 {
fmt.Printf("Status %s", r.Status)
return
}
fmt.Printf("ContentLength: %d\n", r.ContentLength)
buf := make([]byte, 2000000)
l, err := r.Body.Read(buf)
if err != nil && err != io.EOF {
fmt.Printf("Could not read response: %v\n", err)
return
}
if l < len(buf) {
fmt.Printf("Could not read response: %d out of %d\n", l, len(buf))
//return
}
fmt.Printf("%s\n", buf[:l])
}
func compareBlocks(b, bg *EthBlockByNumber) bool {
r := b.Result
rg := bg.Result
if r.Difficulty.ToInt().Cmp(rg.Difficulty.ToInt()) != 0 {
fmt.Printf("Difficulty difference %d %d\n", r.Difficulty.ToInt(), rg.Difficulty.ToInt())
return false
}
if r.Miner != rg.Miner {
fmt.Printf("Miner different %x %x\n", r.Miner, rg.Miner)
return false
}
if len(r.Transactions) != len(rg.Transactions) {
fmt.Printf("Num of txs different: %d %d\n", len(r.Transactions), len(rg.Transactions))
return false
}
for i, tx := range r.Transactions {
txg := rg.Transactions[i]
if tx.From != txg.From {
fmt.Printf("Tx %d different From: %x %x\n", i, tx.From, txg.From)
return false
}
if (tx.To == nil && txg.To != nil) || (tx.To != nil && txg.To == nil) {
fmt.Printf("Tx %d different To nilness: %t %t\n", i, (tx.To == nil), (txg.To == nil))
return false
}
if tx.To != nil && txg.To != nil && *tx.To != *txg.To {
fmt.Printf("Tx %d different To: %x %x\n", i, *tx.To, *txg.To)
return false
}
if tx.Hash != txg.Hash {
fmt.Printf("Tx %x different Hash: %s %s\n", i, tx.Hash, txg.Hash)
return false
}
}
return true
}
func compareTraces(trace, traceg *EthTxTrace) bool {
r := trace.Result
rg := traceg.Result
if r.Gas != rg.Gas {
fmt.Printf("Trace different Gas: %d %d\n", r.Gas, rg.Gas)
return false
}
if r.Failed != rg.Failed {
fmt.Printf("Trace different Failed: %t %t\n", r.Failed, rg.Failed)
return false
}
if r.ReturnValue != rg.ReturnValue {
fmt.Printf("Trace different ReturnValue: %s %s\n", r.ReturnValue, rg.ReturnValue)
return false
}
if len(r.StructLogs) != len(rg.StructLogs) {
fmt.Printf("Trace different length: %d %d\n", len(r.StructLogs), len(rg.StructLogs))
return false
}
for i, l := range r.StructLogs {
lg := rg.StructLogs[i]
if l.Op != lg.Op {
fmt.Printf("Trace different Op: %d %s %s\n", i, l.Op, lg.Op)
return false
}
if l.Pc != lg.Pc {
fmt.Printf("Trace different Pc: %d %d %d\n", i, l.Pc, lg.Pc)
return false
}
}
return true
}
func compareBalances(balance, balanceg *EthBalance) bool {
if balance.Balance.ToInt().Cmp(balanceg.Balance.ToInt()) != 0 {
fmt.Printf("Different balance: %d %d\n", balance.Balance.ToInt(), balanceg.Balance.ToInt())
return false
}
return true
}
func (ma *DebugModifiedAccounts) Print() {
r := ma.Result
rset := make(map[common.Address]struct{})
for _, a := range r {
rset[a] = struct{}{}
}
for a := range rset {
fmt.Printf("%x\n", a)
}
}
func extractAccountMap(ma *DebugModifiedAccounts) map[common.Address]struct{} {
r := ma.Result
rset := make(map[common.Address]struct{})
for _, a := range r {
rset[a] = struct{}{}
}
return rset
}
func printStorageRange(sm map[common.Hash]storageEntry) {
for k := range sm {
fmt.Printf("%x\n", k)
}
}
func compareStorageRanges(sm, smg map[common.Hash]storageEntry) bool {
for k, v := range sm {
if vg, ok := smg[k]; !ok {
fmt.Printf("%x not present in smg\n", k)
return false
} else {
if v.Key == nil {
fmt.Printf("v.Key == nil for %x\n", k)
return false
}
if k != crypto.Keccak256Hash(v.Key[:]) {
fmt.Printf("Sec key %x does not match key %x\n", k, *v.Key)
return false
}
if v.Value != vg.Value {
fmt.Printf("Different values for %x: %x %x [%x]\n", k, v.Value, vg.Value, *v.Key)
return false
}
}
}
for k, v := range smg {
if _, ok := sm[k]; !ok {
fmt.Printf("%x not present in sm\n", k)
return false
}
if k != crypto.Keccak256Hash(v.Key[:]) {
fmt.Printf("Sec key (g) %x does not match key %x\n", k, *v.Key)
return false
}
}
return true
}
/*
// Derived fields. These fields are filled in by the node
// but not secured by consensus.
// block in which the transaction was included
BlockNumber hexutil.Uint64 `json:"blockNumber"`
// hash of the transaction
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
// index of the transaction in the block
TxIndex hexutil.Uint `json:"transactionIndex" gencodec:"required"`
// hash of the block in which the transaction was included
BlockHash common.Hash `json:"blockHash"`
// index of the log in the receipt
Index hexutil.Uint `json:"logIndex" gencodec:"required"`
// The Removed field is true if this log was reverted due to a chain reorganisation.
// You must pay attention to this field if you receive logs through a filter query.
Removed bool `json:"removed"`
*/
func compareReceipts(receipt, receiptg *EthReceipt) bool {
r := receipt.Result
rg := receiptg.Result
if r.TxHash != rg.TxHash {
fmt.Printf("Different tx hashes: %x %x\n", r.TxHash, rg.TxHash)
return false
}
if r.Status != rg.Status {
//fmt.Printf("Different status: %d %d\n", r.Status, rg.Status)
//return false
}
if r.CumulativeGasUsed != rg.CumulativeGasUsed {
fmt.Printf("Different cumulativeGasUsed: %d %d\n", r.CumulativeGasUsed, rg.CumulativeGasUsed)
return false
}
if !bytes.Equal(r.Bloom, rg.Bloom) {
fmt.Printf("Different blooms: %x %x\n", r.Bloom, rg.Bloom)
return false
}
if r.ContractAddress == nil && rg.ContractAddress != nil {
fmt.Printf("Different contract addresses: nil %x\n", rg.ContractAddress)
return false
}
if r.ContractAddress != nil && rg.ContractAddress == nil {
fmt.Printf("Different contract addresses: %x nil\n", r.ContractAddress)
return false
}
if r.ContractAddress != nil && rg.ContractAddress != nil && *r.ContractAddress != *rg.ContractAddress {
fmt.Printf("Different contract addresses: %x %x\n", r.ContractAddress, rg.ContractAddress)
return false
}
if r.GasUsed != rg.GasUsed {
fmt.Printf("Different gasUsed: %d %d\n", r.GasUsed, rg.GasUsed)
return false
}
if len(r.Logs) != len(rg.Logs) {
fmt.Printf("Different log lenths: %d %d\n", len(r.Logs), len(rg.Logs))
return false
}
for i, l := range r.Logs {
lg := rg.Logs[i]
if l.Address != lg.Address {
fmt.Printf("Different log %d addresses: %x %x\n", i, l.Address, lg.Address)
return false
}
if len(l.Topics) != len(lg.Topics) {
fmt.Printf("Different log %d topic lengths: %d %d\n", i, len(l.Topics), len(lg.Topics))
return false
}
for j, t := range l.Topics {
tg := lg.Topics[j]
if t != tg {
fmt.Printf("Different log %d topics %d: %x %x\n", i, j, t, tg)
return false
}
}
if !bytes.Equal(l.Data, lg.Data) {
fmt.Printf("Different log %d data: %x %x\n", i, l.Data, lg.Data)
return false
}
}
return true
}
func compareLogs(logs, logsg *EthLogs) bool {
r := logs.Result
rg := logsg.Result
if len(r) != len(rg) {
fmt.Printf("Different log lenths: %d %d\n", len(r), len(rg))
return false
}
for i, l := range r {
lg := rg[i]
if l.Address != lg.Address {
fmt.Printf("Different log %d addresses: %x %x\n", i, l.Address, lg.Address)
return false
}
if len(l.Topics) != len(lg.Topics) {
fmt.Printf("Different log %d topic lengths: %d %d\n", i, len(l.Topics), len(lg.Topics))
return false
}
for j, t := range l.Topics {
tg := lg.Topics[j]
if t != tg {
fmt.Printf("Different log %d topics %d: %x %x\n", i, j, t, tg)
return false
}
}
if !bytes.Equal(l.Data, lg.Data) {
fmt.Printf("Different log %d data: %x %x\n", i, l.Data, lg.Data)
return false
}
}
return true
}
const Geth = "geth"
const TurboGeth = "turbo_geth"
var routes = map[string]string{
Geth: "http://192.168.1.238:8545",
TurboGeth: "http://192.168.1.126:8545",
}
type CallResult struct {
Target string
Took time.Duration
RequestID int
Method string
RequestBody string
Err error
}
type RequestGenerator struct {
reqID int
client *http.Client
}
func (g *RequestGenerator) blockNumber() string {
const template = `{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":%d}`
return fmt.Sprintf(template, g.reqID)
}
func (g *RequestGenerator) getBlockByNumber(blockNum int) string {
const template = `{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x%x",true],"id":%d}`
return fmt.Sprintf(template, blockNum, g.reqID)
}
func (g *RequestGenerator) storageRangeAt(hash common.Hash, i int, to *common.Address, nextKey common.Hash) string {
const template = `{"jsonrpc":"2.0","method":"debug_storageRangeAt","params":["0x%x", %d,"0x%x","0x%x",%d],"id":%d}`
return fmt.Sprintf(template, hash, i, to, nextKey, 1024, g.reqID)
}
func (g *RequestGenerator) traceTransaction(hash string) string {
const template = `{"jsonrpc":"2.0","method":"debug_traceTransaction","params":["%s"],"id":%d}`
return fmt.Sprintf(template, hash, g.reqID)
}
func (g *RequestGenerator) getTransactionReceipt(hash string) string {
const template = `{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["%s"],"id":%d}`
return fmt.Sprintf(template, hash, g.reqID)
}
func (g *RequestGenerator) getBalance(miner common.Address, bn int) string {
const template = `{"jsonrpc":"2.0","method":"eth_getBalance","params":["0x%x", "0x%x"],"id":%d}`
return fmt.Sprintf(template, miner, bn, g.reqID)
}
func (g *RequestGenerator) getModifiedAccountsByNumber(prevBn int, bn int) string {
const template = `{"jsonrpc":"2.0","method":"debug_getModifiedAccountsByNumber","params":[%d, %d],"id":%d}`
return fmt.Sprintf(template, prevBn, bn, g.reqID)
}
func (g *RequestGenerator) getLogs(prevBn int, bn int, account common.Address) string {
const template = `{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"fromBlock": "0x%x", "toBlock": "0x%x", "address": "0x%x"}],"id":%d}`
return fmt.Sprintf(template, prevBn, bn, account, g.reqID)
}
func (g *RequestGenerator) accountRange(bn int, page []byte) string {
const template = `{ "jsonrpc": "2.0", "method": "debug_accountRange", "params": ["0x%x", "%s", %d, true, true, true], "id":%d}`
encodedKey := base64.StdEncoding.EncodeToString(page)
return fmt.Sprintf(template, bn, encodedKey, 256, g.reqID)
}
func (g *RequestGenerator) call(target string, method, body string, response interface{}) CallResult {
start := time.Now()
err := post(g.client, routes[target], body, response)
return CallResult{
RequestBody: body,
Target: target,
Took: time.Since(start),
RequestID: g.reqID,
Method: method,
Err: err,
}
}
func (g *RequestGenerator) Geth(method, body string, response interface{}) CallResult {
return g.call(Geth, method, body, response)
}
func (g *RequestGenerator) TurboGeth(method, body string, response interface{}) CallResult {
return g.call(TurboGeth, method, body, response)
}
// vegetaWrite (to be run as a goroutine) writing results of server calls into several files:
// results to /$tmp$/turbo_geth_stress_test/results_*.csv
// vegeta format going to files /$tmp$/turbo_geth_stress_test/vegeta_*.txt
func vegetaWrite(enabled bool, resultsCh chan CallResult) {
var err error
var files map[string]map[string]*os.File
var vegetaFiles map[string]map[string]*os.File
if enabled {
files = map[string]map[string]*os.File{
Geth: make(map[string]*os.File),
TurboGeth: make(map[string]*os.File),
}
vegetaFiles = map[string]map[string]*os.File{
Geth: make(map[string]*os.File),
TurboGeth: make(map[string]*os.File),
}
tmpDir := os.TempDir()
fmt.Printf("tmp dir is: %s\n", tmpDir)
dir := path.Join(tmpDir, "turbo_geth_stress_test")
if err = os.MkdirAll(dir, 0770); err != nil {
panic(err)
}
for _, route := range []string{Geth, TurboGeth} {
for _, method := range []string{"eth_getBlockByNumber", "debug_storageRangeAt"} {
file := path.Join(dir, "results_"+route+"_"+method+".csv")
files[route][method], err = os.OpenFile(file, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
if err != nil {
panic(err)
}
}
}
for _, route := range []string{Geth, TurboGeth} {
for _, method := range []string{"eth_getBlockByNumber", "debug_storageRangeAt"} {
file := path.Join(dir, "vegeta_"+route+"_"+method+".txt")
vegetaFiles[route][method], err = os.OpenFile(file, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
if err != nil {
panic(err)
}
}
}
}
for res := range resultsCh {
// If not enabled, simply keep draining the results channel
if enabled {
if res.Err != nil {
fmt.Printf("error response. target: %s, err: %s\n", res.Target, res.Err)
}
// files with call stats
if f, ok := files[res.Target][res.Method]; ok {
row := fmt.Sprintf("%d, %s, %d\n", res.RequestID, res.Method, res.Took.Microseconds())
if _, err := fmt.Fprint(f, row); err != nil {
panic(err)
}
}
// vegeta files, write into all target files
// because if "needCompare" is false - then we don't have responses from TurboGeth
// but we still have enough information to build vegeta file for TurboGeth
for _, target := range []string{Geth, TurboGeth} {
if f, ok := vegetaFiles[target][res.Method]; ok {
template := `{"method": "POST", "url": "%s", "body": "%s", "header": {"Content-Type": ["application/json"]}}`
row := fmt.Sprintf(template, routes[target], base64.StdEncoding.EncodeToString([]byte(res.RequestBody)))
if _, err := fmt.Fprint(f, row+"\n"); err != nil {
panic(err)
}
}
}
}
}
}
// bench1 compares response of TurboGeth with Geth
// but also can be used for comparing RPCDaemon with Geth
// parameters:
// needCompare - if false - doesn't call TurboGeth and doesn't compare responses
// use false value - to generate vegeta files, it's faster but we can generate vegeta files for Geth and Turbogeth
// fullTest - if false - then call only methods which RPCDaemon currently supports
func bench1(needCompare bool, fullTest bool) {
var client = &http.Client{
Timeout: time.Second * 600,
}
resultsCh := make(chan CallResult, 1000)
defer close(resultsCh)
go vegetaWrite(false, resultsCh)
var res CallResult
reqGen := &RequestGenerator{
client: client,
}
reqGen.reqID++
var blockNumber EthBlockNumber
res = reqGen.TurboGeth("eth_blockNumber", reqGen.blockNumber(), &blockNumber)
resultsCh <- res
if res.Err != nil {
fmt.Printf("Could not get block number: %v\n", res.Err)
return
}
if blockNumber.Error != nil {
fmt.Printf("Error getting block number: %d %s\n", blockNumber.Error.Code, blockNumber.Error.Message)
return
}
lastBlock := blockNumber.Number
if lastBlock > 5000000 {
lastBlock = 5000000
}
fmt.Printf("Last block: %d\n", lastBlock)
accounts := make(map[common.Address]struct{})
firstBn := 49000
prevBn := firstBn
storageCounter := 0
for bn := firstBn; bn <= int(lastBlock); bn++ {
reqGen.reqID++
var b EthBlockByNumber
res = reqGen.Geth("eth_getBlockByNumber", reqGen.getBlockByNumber(bn), &b)
resultsCh <- res
if res.Err != nil {
fmt.Printf("Could not retrieve block %d: %v\n", bn, res.Err)
return
}
if b.Error != nil {
fmt.Printf("Error retrieving block: %d %s\n", b.Error.Code, b.Error.Message)
}
if needCompare {
var bg EthBlockByNumber
res = reqGen.TurboGeth("eth_getBlockByNumber", reqGen.getBlockByNumber(bn), &bg)
if res.Err != nil {
fmt.Printf("Could not retrieve block g %d: %v\n", bn, res.Err)
return
}
if bg.Error != nil {
fmt.Printf("Error retrieving block g: %d %s\n", bg.Error.Code, bg.Error.Message)
return
}
if !compareBlocks(&b, &bg) {
fmt.Printf("Block difference for %d\n", bn)
return
}
}
accounts[b.Result.Miner] = struct{}{}
for i, tx := range b.Result.Transactions {
accounts[tx.From] = struct{}{}
if tx.To != nil {
accounts[*tx.To] = struct{}{}
}
if tx.To != nil && tx.Gas.ToInt().Uint64() > 21000 {
storageCounter++
if storageCounter == 100 {
storageCounter = 0
var sm map[common.Hash]storageEntry
var smGeth map[common.Hash]storageEntry
nextKey := &common.Hash{}
nextKeyGeth := &common.Hash{}
var sr DebugStorageRange
var srGeth DebugStorageRange
counter := 16
for nextKey != nil && counter > 0 {
sm = make(map[common.Hash]storageEntry)
smGeth = make(map[common.Hash]storageEntry)
reqGen.reqID++
res = reqGen.TurboGeth("debug_storageRangeAt", reqGen.storageRangeAt(b.Result.Hash, i, tx.To, *nextKey), &sr)
resultsCh <- res
if res.Err != nil {
fmt.Printf("Could not get storageRange: %s: %v\n", tx.Hash, res.Err)
break
}
if sr.Error != nil {
fmt.Printf("Error getting storageRange: %d %s\n", sr.Error.Code, sr.Error.Message)
break
} else {
nextKey = sr.Result.NextKey
for k, v := range sr.Result.Storage {
sm[k] = v
}
}
res = reqGen.Geth("debug_storageRangeAt", reqGen.storageRangeAt(b.Result.Hash, i, tx.To, *nextKeyGeth), &srGeth)
resultsCh <- res
if res.Err != nil {
fmt.Printf("Could not get storageRange geth: %s: %v\n", tx.Hash, res.Err)
break
}
if srGeth.Error != nil {
fmt.Printf("Error getting storageRange geth: %d %s\n", srGeth.Error.Code, srGeth.Error.Message)
break
} else {
nextKeyGeth = srGeth.Result.NextKey
for k, v := range srGeth.Result.Storage {
smGeth[k] = v
}
}
if nextKey != nil && nextKeyGeth != nil && *nextKey != *nextKeyGeth {
fmt.Printf("Non matching nextKey %x %x\n", *nextKey, *nextKeyGeth)
fmt.Printf("len(sm) %d, len(smg) %d\n", len(sm), len(smGeth))
fmt.Printf("================sm\n")
printStorageRange(sm)
fmt.Printf("================smg\n")
printStorageRange(smGeth)
return
}
if !compareStorageRanges(sm, smGeth) {
fmt.Printf("len(sm) %d, len(smGeth) %d\n", len(sm), len(smGeth))
fmt.Printf("================sm\n")
printStorageRange(sm)
fmt.Printf("================smg\n")
printStorageRange(smGeth)
return
}
counter--
}
}
}
if !fullTest {
continue // TODO: remove me
}
reqGen.reqID++
var trace EthTxTrace
res = reqGen.Geth("debug_traceTransaction", reqGen.traceTransaction(tx.Hash), &trace)
resultsCh <- res
if res.Err != nil {
fmt.Printf("Could not trace transaction %s: %v\n", tx.Hash, res.Err)
print(client, routes[Geth], reqGen.traceTransaction(tx.Hash))
}
if trace.Error != nil {
fmt.Printf("Error tracing transaction: %d %s\n", trace.Error.Code, trace.Error.Message)
}
if needCompare {
var traceg EthTxTrace
res = reqGen.TurboGeth("debug_traceTransaction", reqGen.traceTransaction(tx.Hash), &traceg)
resultsCh <- res
if res.Err != nil {
fmt.Printf("Could not trace transaction g %s: %v\n", tx.Hash, res.Err)
print(client, routes[TurboGeth], reqGen.traceTransaction(tx.Hash))
return
}
if traceg.Error != nil {
fmt.Printf("Error tracing transaction g: %d %s\n", traceg.Error.Code, traceg.Error.Message)
return
}
if res.Err == nil && trace.Error == nil {
if !compareTraces(&trace, &traceg) {
fmt.Printf("Different traces block %d, tx %s\n", bn, tx.Hash)
return
}
}
}
reqGen.reqID++
var receipt EthReceipt
res = reqGen.Geth("eth_getTransactionReceipt", reqGen.getTransactionReceipt(tx.Hash), &receipt)
resultsCh <- res
if res.Err != nil {
fmt.Printf("Count not get receipt: %s: %v\n", tx.Hash, res.Err)
print(client, routes[Geth], reqGen.getTransactionReceipt(tx.Hash))
return
}
if receipt.Error != nil {
fmt.Printf("Error getting receipt: %d %s\n", receipt.Error.Code, receipt.Error.Message)
return
}
if needCompare {
var receiptg EthReceipt
res = reqGen.TurboGeth("eth_getTransactionReceipt", reqGen.getTransactionReceipt(tx.Hash), &receiptg)
resultsCh <- res
if res.Err != nil {
fmt.Printf("Count not get receipt g: %s: %v\n", tx.Hash, res.Err)
print(client, routes[TurboGeth], reqGen.getTransactionReceipt(tx.Hash))
return
}
if receiptg.Error != nil {
fmt.Printf("Error getting receipt g: %d %s\n", receiptg.Error.Code, receiptg.Error.Message)
return
}
if !compareReceipts(&receipt, &receiptg) {
fmt.Printf("Different receipts block %d, tx %s\n", bn, tx.Hash)
print(client, routes[Geth], reqGen.getTransactionReceipt(tx.Hash))
print(client, routes[TurboGeth], reqGen.getTransactionReceipt(tx.Hash))
return
}
}
}
reqGen.reqID++
var balance EthBalance
res = reqGen.Geth("eth_getBalance", reqGen.getBalance(b.Result.Miner, bn), &balance)
resultsCh <- res
if res.Err != nil {
fmt.Printf("Could not get account balance: %v\n", res.Err)
return
}
if balance.Error != nil {
fmt.Printf("Error getting account balance: %d %s", balance.Error.Code, balance.Error.Message)
return
}
if needCompare {
var balanceg EthBalance
res = reqGen.TurboGeth("eth_getBalance", reqGen.getBalance(b.Result.Miner, bn), &balanceg)
resultsCh <- res
if res.Err != nil {
fmt.Printf("Could not get account balance g: %v\n", res.Err)
return
}
if balanceg.Error != nil {
fmt.Printf("Error getting account balance g: %d %s\n", balanceg.Error.Code, balanceg.Error.Message)
return
}
if !compareBalances(&balance, &balanceg) {
fmt.Printf("Miner %x balance difference for block %d\n", b.Result.Miner, bn)
return
}
}
if prevBn < bn && bn%100 == 0 {
// Checking modified accounts
reqGen.reqID++
var mag DebugModifiedAccounts
res = reqGen.TurboGeth("debug_getModifiedAccountsByNumber", reqGen.getModifiedAccountsByNumber(prevBn, bn), &mag)
resultsCh <- res
if res.Err != nil {
fmt.Printf("Could not get modified accounts g: %v\n", res.Err)
return
}
if mag.Error != nil {
fmt.Printf("Error getting modified accounts g: %d %s\n", mag.Error.Code, mag.Error.Message)
return
}
if res.Err == nil && mag.Error == nil {
accountSet := extractAccountMap(&mag)
for account := range accountSet {
reqGen.reqID++
var logs EthLogs
res = reqGen.Geth("eth_getLogs", reqGen.getLogs(prevBn, bn, account), &logs)
resultsCh <- res
if res.Err != nil {
fmt.Printf("Could not get logs for account %x: %v\n", account, res.Err)
return
}
if logs.Error != nil {
fmt.Printf("Error getting logs for account %x: %d %s\n", account, logs.Error.Code, logs.Error.Message)
return
}
var logsg EthLogs
res = reqGen.TurboGeth("eth_getLogs", reqGen.getLogs(prevBn, bn, account), &logsg)
resultsCh <- res
if res.Err != nil {
fmt.Printf("Could not get logs for account g %x: %v\n", account, res.Err)
return
}
if logsg.Error != nil {
fmt.Printf("Error getting logs for account g %x: %d %s\n", account, logsg.Error.Code, logsg.Error.Message)
return
}
if !compareLogs(&logs, &logsg) {
fmt.Printf("Different logs for account %x and block %d-%d\n", account, prevBn, bn)
return
}
}
}
fmt.Printf("Done blocks %d-%d, modified accounts: %d\n", prevBn, bn, len(mag.Result))
page := common.Hash{}.Bytes()
pageGeth := common.Hash{}.Bytes()
var accRangeTG map[common.Address]state.DumpAccount
var accRangeGeth map[common.Address]state.DumpAccount
for len(page) > 0 {
accRangeTG = make(map[common.Address]state.DumpAccount)
accRangeGeth = make(map[common.Address]state.DumpAccount)
var sr DebugAccountRange
reqGen.reqID++
res = reqGen.TurboGeth("debug_accountRange", reqGen.accountRange(bn, page), &sr)
resultsCh <- res
if res.Err != nil {
fmt.Printf("Could not get accountRange: %v\n", res.Err)
return
}
if sr.Error != nil {
fmt.Printf("Error getting accountRange: %d %s\n", sr.Error.Code, sr.Error.Message)
break
} else {
page = sr.Result.Next
for k, v := range sr.Result.Accounts {
accRangeTG[k] = v
}
}
var srGeth DebugAccountRange
res = reqGen.Geth("debug_accountRange", reqGen.accountRange(bn, pageGeth), &srGeth)
resultsCh <- res
if res.Err != nil {
fmt.Printf("Could not get accountRange geth: %v\n", res.Err)
return
}
if srGeth.Error != nil {
fmt.Printf("Error getting accountRange geth: %d %s\n", srGeth.Error.Code, srGeth.Error.Message)
break
} else {
pageGeth = srGeth.Result.Next
for k, v := range srGeth.Result.Accounts {
accRangeGeth[k] = v
}
}
if !bytes.Equal(page, pageGeth) {
fmt.Printf("Different next page keys: %x geth %x", page, pageGeth)
}
if !compareAccountRanges(accRangeTG, accRangeGeth) {
fmt.Printf("Different in account ranges tx\n")
return
}
}
prevBn = bn
}
}
}
func bench2() {
var client = &http.Client{
Timeout: time.Second * 600,
}
req_id := 0
turbogeth_url := "http://localhost:8545"
req_id++
template := `
{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":%d}
`
var blockNumber EthBlockNumber
if err := post(client, turbogeth_url, fmt.Sprintf(template, req_id), &blockNumber); err != nil {
fmt.Printf("Could not get block number: %v\n", err)
return
}
if blockNumber.Error != nil {
fmt.Printf("Error getting block number: %d %s\n", blockNumber.Error.Code, blockNumber.Error.Message)
return
}
lastBlock := blockNumber.Number
fmt.Printf("Last block: %d\n", lastBlock)
firstBn := 1720000 - 2
prevBn := firstBn
for bn := firstBn; bn <= int(lastBlock); bn++ {
req_id++
template := `
{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x%x",true],"id":%d}
`
var b EthBlockByNumber
if err := post(client, turbogeth_url, fmt.Sprintf(template, bn, req_id), &b); err != nil {
fmt.Printf("Could not retrieve block %d: %v\n", bn, err)
return
}
if b.Error != nil {
fmt.Printf("Error retrieving block: %d %s\n", b.Error.Code, b.Error.Message)
}
for i, tx := range b.Result.Transactions {
if tx.To != nil && tx.Gas.ToInt().Uint64() > 21000 {
// Request storage range
// blockHash common.Hash, txIndex int, contractAddress common.Address, keyStart hexutil.Bytes, maxResult int
req_id++
template = `
{"jsonrpc":"2.0","method":"debug_storageRangeAt","params":["0x%x", %d,"0x%x","0x%x",%d],"id":%d}
`
sm := make(map[common.Hash]storageEntry)
nextKey := &common.Hash{}
for nextKey != nil {
var sr DebugStorageRange
if err := post(client, turbogeth_url, fmt.Sprintf(template, b.Result.Hash, i, tx.To, *nextKey, 1024, req_id), &sr); err != nil {
fmt.Printf("Could not get storageRange: %x: %v\n", tx.Hash, err)
return
}
if sr.Error != nil {
fmt.Printf("Error getting storageRange: %d %s\n", sr.Error.Code, sr.Error.Message)
break
} else {
nextKey = sr.Result.NextKey
for k, v := range sr.Result.Storage {
sm[k] = v
if v.Key == nil {
fmt.Printf("No key for sec key: %x\n", k)
} else if k != crypto.Keccak256Hash(v.Key[:]) {
fmt.Printf("Different sec key: %x %x (%x), value %x\n", k, crypto.Keccak256Hash(v.Key[:]), *(v.Key), v.Value)
} else {
fmt.Printf("Keys: %x %x, value %x\n", *(v.Key), k, v.Value)
}
}
}
}
fmt.Printf("storageRange: %d\n", len(sm))
}
}
if prevBn < bn && bn%1000 == 0 {
// Checking modified accounts
req_id++
template = `
{"jsonrpc":"2.0","method":"debug_getModifiedAccountsByNumber","params":[%d, %d],"id":%d}
`
var ma DebugModifiedAccounts
if err := post(client, turbogeth_url, fmt.Sprintf(template, prevBn, bn, req_id), &ma); err != nil {
fmt.Printf("Could not get modified accounts: %v\n", err)
return
}
if ma.Error != nil {
fmt.Printf("Error getting modified accounts: %d %s\n", ma.Error.Code, ma.Error.Message)
return
}
fmt.Printf("Done blocks %d-%d, modified accounts: %d\n", prevBn, bn, len(ma.Result))
prevBn = bn
}
}
}
func bench3() {
var client = &http.Client{
Timeout: time.Second * 600,
}
geth_url := "http://localhost:8545"
turbogeth_url := "http://localhost:9545"
blockhash := common.HexToHash("0xdf15213766f00680c6a20ba76ba2cc9534435e19bc490039f3a7ef42095c8d13")
req_id := 1
pageSize := 256
req_id++
template := `{ "jsonrpc": "2.0", "method": "debug_accountRange", "params": ["0x1", "%s", %d, true, true, true], "id":%d}`
page := common.Hash{}.Bytes()
accRangeTG := make(map[common.Address]state.DumpAccount)
for len(page) > 0 {
encodedKey := base64.StdEncoding.EncodeToString(page)
var sr DebugAccountRange
if err := post(client, turbogeth_url, fmt.Sprintf(template, encodedKey, pageSize, req_id), &sr); err != nil {
fmt.Printf("Could not get accountRange: %v\n", err)
return
}
if sr.Error != nil {
fmt.Printf("Error getting accountRange: %d %s\n", sr.Error.Code, sr.Error.Message)
break
} else {
page = sr.Result.Next
for k, v := range sr.Result.Accounts {
accRangeTG[k] = v
}
}
}
accRangeGeth := make(map[common.Address]state.DumpAccount)
page = common.Hash{}.Bytes()
for len(page) > 0 {
encodedKey := base64.StdEncoding.EncodeToString(page)
var sr DebugAccountRange
if err := post(client, geth_url, fmt.Sprintf(template, encodedKey, pageSize, req_id), &sr); err != nil {
fmt.Printf("Could not get accountRange: %v\n", err)
return
}
if sr.Error != nil {
fmt.Printf("Error getting accountRange: %d %s\n", sr.Error.Code, sr.Error.Message)
break
} else {
page = sr.Result.Next
for k, v := range sr.Result.Accounts {
accRangeTG[k] = v
}
}
}
if !compareAccountRanges(accRangeTG, accRangeGeth) {
fmt.Printf("Different in account ranges tx\n")
return
}
fmt.Println("debug_accountRanges... OK!")
template = `{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x%x",true],"id":%d}`
var b EthBlockByNumber
if err := post(client, turbogeth_url, fmt.Sprintf(template, 1720000, req_id), &b); err != nil {
fmt.Printf("Could not retrieve block %d: %v\n", 1720000, err)
return
}
if b.Error != nil {
fmt.Printf("Error retrieving block: %d %s\n", b.Error.Code, b.Error.Message)
}
for txindex := 0; txindex < 18; txindex++ {
txhash := b.Result.Transactions[txindex].Hash
req_id++
template = `
{"jsonrpc":"2.0","method":"debug_traceTransaction","params":["%s"],"id":%d}
`
var trace EthTxTrace
if err := post(client, turbogeth_url, fmt.Sprintf(template, txhash, req_id), &trace); err != nil {
fmt.Printf("Could not trace transaction %s: %v\n", txhash, err)
print(client, turbogeth_url, fmt.Sprintf(template, txhash, req_id))
return
}
if trace.Error != nil {
fmt.Printf("Error tracing transaction: %d %s\n", trace.Error.Code, trace.Error.Message)
}
var traceg EthTxTrace
if err := post(client, geth_url, fmt.Sprintf(template, txhash, req_id), &traceg); err != nil {
fmt.Printf("Could not trace transaction g %s: %v\n", txhash, err)
print(client, geth_url, fmt.Sprintf(template, txhash, req_id))
return
}
if traceg.Error != nil {
fmt.Printf("Error tracing transaction g: %d %s\n", traceg.Error.Code, traceg.Error.Message)
return
}
//print(client, turbogeth_url, fmt.Sprintf(template, txhash, req_id))
if !compareTraces(&trace, &traceg) {
fmt.Printf("Different traces block %d, tx %s\n", 1720000, txhash)
return
}
}
to := common.HexToAddress("0xbb9bc244d798123fde783fcc1c72d3bb8c189413")
sm := make(map[common.Hash]storageEntry)
start := common.HexToHash("0x5aa12c260b07325d83f0c9170a2c667948d0247cad4ad999cd00148658b0552d")
req_id++
template = `
{"jsonrpc":"2.0","method":"debug_storageRangeAt","params":["0x%x", %d,"0x%x","0x%x",%d],"id":%d}
`
i := 18
nextKey := &start
for nextKey != nil {
var sr DebugStorageRange
if err := post(client, turbogeth_url, fmt.Sprintf(template, blockhash, i, to, *nextKey, 1024, req_id), &sr); err != nil {
fmt.Printf("Could not get storageRange: %v\n", err)
return
}
if sr.Error != nil {
fmt.Printf("Error getting storageRange: %d %s\n", sr.Error.Code, sr.Error.Message)
break
} else {
nextKey = sr.Result.NextKey
for k, v := range sr.Result.Storage {
sm[k] = v
}
}
}
fmt.Printf("storageRange: %d\n", len(sm))
smg := make(map[common.Hash]storageEntry)
nextKey = &start
for nextKey != nil {
var srg DebugStorageRange
if err := post(client, geth_url, fmt.Sprintf(template, blockhash, i, to, *nextKey, 1024, req_id), &srg); err != nil {
fmt.Printf("Could not get storageRange g: %v\n", err)
return
}
if srg.Error != nil {
fmt.Printf("Error getting storageRange g: %d %s\n", srg.Error.Code, srg.Error.Message)
break
} else {
nextKey = srg.Result.NextKey
for k, v := range srg.Result.Storage {
smg[k] = v
}
}
}
fmt.Printf("storageRange g: %d\n", len(smg))
if !compareStorageRanges(sm, smg) {
fmt.Printf("Different in storage ranges tx\n")
return
}
}
func compareAccountRanges(tg, geth map[common.Address]state.DumpAccount) bool {
allAddresses := make(map[common.Address]struct{})
for k := range tg {
allAddresses[k] = struct{}{}
}
for k := range geth {
allAddresses[k] = struct{}{}
}
for addr := range allAddresses {
tgAcc, tgOk := tg[addr]
if !tgOk {
fmt.Printf("missing account in TurboGeth %x\n", addr)
return false
}
gethAcc, gethOk := geth[addr]
if !gethOk {
fmt.Printf("missing account in Geth %x\n", addr)
return false
}
different := false
if tgAcc.Balance != gethAcc.Balance {
fmt.Printf("Different balance for %x: turbo %s, geth %s\n", addr, tgAcc.Balance, gethAcc.Balance)
different = true
}
if tgAcc.Nonce != gethAcc.Nonce {
fmt.Printf("Different nonce for %x: turbo %d, geth %d\n", addr, tgAcc.Nonce, gethAcc.Nonce)
different = true
}
// We do not compare Root, because Turbo-geth does not compute it
if tgAcc.CodeHash != gethAcc.CodeHash {
fmt.Printf("Different codehash for %x: turbo %s, geth %s\n", addr, tgAcc.CodeHash, gethAcc.CodeHash)
different = true
}
if tgAcc.Code != gethAcc.Code {
fmt.Printf("Different codehash for %x: turbo %s, geth %s\n", addr, tgAcc.Code, gethAcc.Code)
different = true
}
if different {
return false
}
}
return true
}
func bench4() {
var client = &http.Client{
Timeout: time.Second * 600,
}
turbogeth_url := "http://localhost:9545"
blockhash := common.HexToHash("0xdf15213766f00680c6a20ba76ba2cc9534435e19bc490039f3a7ef42095c8d13")
req_id := 1
template := `
{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x%x",true],"id":%d}
`
var b EthBlockByNumber
if err := post(client, turbogeth_url, fmt.Sprintf(template, 1720000, req_id), &b); err != nil {
fmt.Printf("Could not retrieve block %d: %v\n", 1720000, err)
return
}
if b.Error != nil {
fmt.Printf("Error retrieving block: %d %s\n", b.Error.Code, b.Error.Message)
}
for txindex := 0; txindex < 6; txindex++ {
txhash := b.Result.Transactions[txindex].Hash
req_id++
template = `
{"jsonrpc":"2.0","method":"debug_traceTransaction","params":["%s"],"id":%d}
`
var trace EthTxTrace
if err := post(client, turbogeth_url, fmt.Sprintf(template, txhash, req_id), &trace); err != nil {
fmt.Printf("Could not trace transaction %s: %v\n", txhash, err)
print(client, turbogeth_url, fmt.Sprintf(template, txhash, req_id))
return
}
if trace.Error != nil {
fmt.Printf("Error tracing transaction: %d %s\n", trace.Error.Code, trace.Error.Message)
}
print(client, turbogeth_url, fmt.Sprintf(template, txhash, req_id))
}
to := common.HexToAddress("0x8b3b3b624c3c0397d3da8fd861512393d51dcbac")
sm := make(map[common.Hash]storageEntry)
start := common.HexToHash("0xa283ff49a55f86420a4acd5835658d8f45180db430c7b0d7ae98da5c64f620dc")
req_id++
template = `
{"jsonrpc":"2.0","method":"debug_storageRangeAt","params":["0x%x", %d,"0x%x","0x%x",%d],"id":%d}
`
i := 6
nextKey := &start
for nextKey != nil {
var sr DebugStorageRange
if err := post(client, turbogeth_url, fmt.Sprintf(template, blockhash, i, to, *nextKey, 1024, req_id), &sr); err != nil {
fmt.Printf("Could not get storageRange: %v\n", err)
return
}
if sr.Error != nil {
fmt.Printf("Error getting storageRange: %d %s\n", sr.Error.Code, sr.Error.Message)
break
} else {
nextKey = sr.Result.NextKey
for k, v := range sr.Result.Storage {
sm[k] = v
}
}
}
fmt.Printf("storageRange: %d\n", len(sm))
}
func bench5() {
var client = &http.Client{
Timeout: time.Second * 600,
}
turbogethURL := routes[TurboGeth]
file, err := os.Open("txs.txt")
if err != nil {
panic(err)
}
req_id := 0
template := `{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["0x%s"],"id":%d}`
var receipt EthReceipt
scanner := bufio.NewScanner(file)
for scanner.Scan() {
req_id++
if err = post(client, turbogethURL, fmt.Sprintf(template, scanner.Text(), req_id), &receipt); err != nil {
fmt.Printf("Count not get receipt: %s: %v\n", scanner.Text(), err)
return
}
if receipt.Error != nil {
fmt.Printf("Error getting receipt: %d %s\n", receipt.Error.Code, receipt.Error.Message)
return
}
}
err = scanner.Err()
if err != nil {
panic(err)
}
}
func bench6() {
var client = &http.Client{
Timeout: time.Second * 600,
}
req_id := 0
turbogeth_url := "http://localhost:8545"
req_id++
template := `
{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":%d}
`
var blockNumber EthBlockNumber
if err := post(client, turbogeth_url, fmt.Sprintf(template, req_id), &blockNumber); err != nil {
fmt.Printf("Could not get block number: %v\n", err)
return
}
if blockNumber.Error != nil {
fmt.Printf("Error getting block number: %d %s\n", blockNumber.Error.Code, blockNumber.Error.Message)
return
}
lastBlock := blockNumber.Number
fmt.Printf("Last block: %d\n", lastBlock)
accounts := make(map[common.Address]struct{})
firstBn := 100000
for bn := firstBn; bn <= int(lastBlock); bn++ {
req_id++
template := `
{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x%x",true],"id":%d}
`
var b EthBlockByNumber
if err := post(client, turbogeth_url, fmt.Sprintf(template, bn, req_id), &b); err != nil {
fmt.Printf("Could not retrieve block %d: %v\n", bn, err)
return
}
if b.Error != nil {
fmt.Printf("Error retrieving block: %d %s\n", b.Error.Code, b.Error.Message)
}
accounts[b.Result.Miner] = struct{}{}
for _, tx := range b.Result.Transactions {
accounts[tx.From] = struct{}{}
if tx.To != nil {
accounts[*tx.To] = struct{}{}
}
req_id++
template = `
{"jsonrpc":"2.0","method":"eth_getTransactionReceipt","params":["%s"],"id":%d}
`
var receipt EthReceipt
if err := post(client, turbogeth_url, fmt.Sprintf(template, tx.Hash, req_id), &receipt); err != nil {
fmt.Printf("Count not get receipt: %s: %v\n", tx.Hash, err)
print(client, turbogeth_url, fmt.Sprintf(template, tx.Hash, req_id))
return
}
if receipt.Error != nil {
fmt.Printf("Error getting receipt: %d %s\n", receipt.Error.Code, receipt.Error.Message)
return
}
}
}
}
func bench7() {
var client = &http.Client{
Timeout: time.Second * 600,
}
turbogethURL := routes[TurboGeth]
gethURL := routes[Geth]
blockhash := common.HexToHash("0xdd3eb495312b11621669be45a2d50f8a66f2616bc72a610e2cbf1aebf9e4a9aa")
reqID := 1
to := common.HexToAddress("0xbb9bc244d798123fde783fcc1c72d3bb8c189413")
var sm map[common.Hash]storageEntry
var smg map[common.Hash]storageEntry
start := common.HexToHash("0x4a17477338cba00d8a94336ef62ea15f68e77ad0ca738fa405daa13bf0874134")
reqID++
template := `
{"jsonrpc":"2.0","method":"debug_storageRangeAt","params":["0x%x", %d,"0x%x","0x%x",%d],"id":%d}
`
i := 0
nextKey := &start
nextKeyG := &start
for nextKey != nil {
sm = make(map[common.Hash]storageEntry)
smg = make(map[common.Hash]storageEntry)
var sr DebugStorageRange
if err := post(client, turbogethURL, fmt.Sprintf(template, blockhash, i, to, *nextKey, 2, reqID), &sr); err != nil {
fmt.Printf("Could not get storageRange: %v\n", err)
return
}
if sr.Error != nil {
fmt.Printf("Error getting storageRange: %d %s\n", sr.Error.Code, sr.Error.Message)
break
} else {
nextKey = sr.Result.NextKey
for k, v := range sr.Result.Storage {
sm[k] = v
if v.Key == nil {
fmt.Printf("%x: %x", k, v)
}
}
}
var srg DebugStorageRange
if err := post(client, gethURL, fmt.Sprintf(template, blockhash, i, to, *nextKeyG, 2, reqID), &srg); err != nil {
fmt.Printf("Could not get storageRange: %v\n", err)
return
}
if srg.Error != nil {
fmt.Printf("Error getting storageRange: %d %s\n", sr.Error.Code, sr.Error.Message)
break
} else {
for k, v := range srg.Result.Storage {
smg[k] = v
if v.Key == nil {
fmt.Printf("%x: %x", k, v)
}
}
nextKeyG = srg.Result.NextKey
if *nextKey != *nextKeyG {
fmt.Printf("Non matching nextKey %x %x\n", *nextKey, *nextKeyG)
fmt.Printf("len(sm) %d, len(smg) %d\n", len(sm), len(smg))
fmt.Printf("================sm\n")
printStorageRange(sm)
fmt.Printf("================smg\n")
printStorageRange(smg)
return
}
}
if !compareStorageRanges(sm, smg) {
fmt.Printf("len(sm) %d, len(smg) %d\n", len(sm), len(smg))
fmt.Printf("================sm\n")
printStorageRange(sm)
fmt.Printf("================smg\n")
printStorageRange(smg)
return
}
}
fmt.Printf("storageRange: %d\n", len(sm))
}
func bench8() {
var client = &http.Client{
Timeout: time.Second * 600,
}
turbogethURL := "http://localhost:8545"
reqID := 1
to := common.HexToAddress("0x9653c9859b18f8777fe4eec9a67c9f64f3d6f62a")
reqID++
template := `{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"fromBlock": "0x%x", "toBlock": "0x%x", "address": "0x%x"}],"id":%d}`
var logs EthLogs
if err := post(client, turbogethURL, fmt.Sprintf(template, 49000, 49100, to, reqID), &logs); err != nil {
fmt.Printf("Could not get eth_getLogs: %v\n", err)
return
}
if logs.Error != nil {
fmt.Printf("Error getting eth_getLogs: %d %s\n", logs.Error.Code, logs.Error.Message)
}
}
func main() {
var (
ostream log.Handler
glogger *log.GlogHandler
)
usecolor := (isatty.IsTerminal(os.Stderr.Fd()) || isatty.IsCygwinTerminal(os.Stderr.Fd())) && os.Getenv("TERM") != "dumb"
output := io.Writer(os.Stderr)
if usecolor {
output = colorable.NewColorableStderr()
}
ostream = log.StreamHandler(output, log.TerminalFormat(usecolor))
glogger = log.NewGlogHandler(ostream)
log.Root().SetHandler(glogger)
glogger.Verbosity(log.Lvl(3)) // 3 == verbosity INFO
flag.Parse()
switch *action {
case "proofs":
proofs(*chaindata, *url, *block)
case "fixState":
fixState(*chaindata, *url)
case "bench1":
bench1(true, true)
case "bench3":
bench3()
case "bench7":
bench7()
case "bench8":
bench8()
}
}