mirror of https://github.com/ethereum/go-ethereum
parent
faab931ce1
commit
09d0d55fc5
@ -0,0 +1,169 @@ |
|||||||
|
package api |
||||||
|
|
||||||
|
import ( |
||||||
|
"fmt" |
||||||
|
|
||||||
|
"github.com/ethereum/ethash" |
||||||
|
"github.com/ethereum/go-ethereum/core/state" |
||||||
|
"github.com/ethereum/go-ethereum/core/vm" |
||||||
|
"github.com/ethereum/go-ethereum/eth" |
||||||
|
"github.com/ethereum/go-ethereum/rlp" |
||||||
|
"github.com/ethereum/go-ethereum/rpc/codec" |
||||||
|
"github.com/ethereum/go-ethereum/rpc/shared" |
||||||
|
"github.com/ethereum/go-ethereum/xeth" |
||||||
|
) |
||||||
|
|
||||||
|
const ( |
||||||
|
DebugVersion = "1.0.0" |
||||||
|
) |
||||||
|
|
||||||
|
var ( |
||||||
|
// mapping between methods and handlers
|
||||||
|
DebugMapping = map[string]debughandler{ |
||||||
|
"debug_dumpBlock": (*DebugApi).DumpBlock, |
||||||
|
"debug_getBlockRlp": (*DebugApi).GetBlockRlp, |
||||||
|
"debug_printBlock": (*DebugApi).PrintBlock, |
||||||
|
"debug_processBlock": (*DebugApi).ProcessBlock, |
||||||
|
"debug_seedHash": (*DebugApi).SeedHash, |
||||||
|
"debug_setHead": (*DebugApi).SetHead, |
||||||
|
} |
||||||
|
) |
||||||
|
|
||||||
|
// debug callback handler
|
||||||
|
type debughandler func(*DebugApi, *shared.Request) (interface{}, error) |
||||||
|
|
||||||
|
// admin api provider
|
||||||
|
type DebugApi struct { |
||||||
|
xeth *xeth.XEth |
||||||
|
ethereum *eth.Ethereum |
||||||
|
methods map[string]debughandler |
||||||
|
codec codec.ApiCoder |
||||||
|
} |
||||||
|
|
||||||
|
// create a new debug api instance
|
||||||
|
func NewDebugApi(xeth *xeth.XEth, ethereum *eth.Ethereum, coder codec.Codec) *DebugApi { |
||||||
|
return &DebugApi{ |
||||||
|
xeth: xeth, |
||||||
|
ethereum: ethereum, |
||||||
|
methods: DebugMapping, |
||||||
|
codec: coder.New(nil), |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// collection with supported methods
|
||||||
|
func (self *DebugApi) Methods() []string { |
||||||
|
methods := make([]string, len(self.methods)) |
||||||
|
i := 0 |
||||||
|
for k := range self.methods { |
||||||
|
methods[i] = k |
||||||
|
i++ |
||||||
|
} |
||||||
|
return methods |
||||||
|
} |
||||||
|
|
||||||
|
// Execute given request
|
||||||
|
func (self *DebugApi) Execute(req *shared.Request) (interface{}, error) { |
||||||
|
if callback, ok := self.methods[req.Method]; ok { |
||||||
|
return callback(self, req) |
||||||
|
} |
||||||
|
|
||||||
|
return nil, &shared.NotImplementedError{req.Method} |
||||||
|
} |
||||||
|
|
||||||
|
func (self *DebugApi) Name() string { |
||||||
|
return DebugApiName |
||||||
|
} |
||||||
|
|
||||||
|
func (self *DebugApi) PrintBlock(req *shared.Request) (interface{}, error) { |
||||||
|
args := new(BlockNumArg) |
||||||
|
if err := self.codec.Decode(req.Params, &args); err != nil { |
||||||
|
return nil, shared.NewDecodeParamError(err.Error()) |
||||||
|
} |
||||||
|
|
||||||
|
block := self.xeth.EthBlockByNumber(args.BlockNumber) |
||||||
|
return fmt.Sprintf("%s", block), nil |
||||||
|
} |
||||||
|
|
||||||
|
func (self *DebugApi) DumpBlock(req *shared.Request) (interface{}, error) { |
||||||
|
args := new(BlockNumArg) |
||||||
|
if err := self.codec.Decode(req.Params, &args); err != nil { |
||||||
|
return nil, shared.NewDecodeParamError(err.Error()) |
||||||
|
} |
||||||
|
|
||||||
|
block := self.xeth.EthBlockByNumber(args.BlockNumber) |
||||||
|
if block == nil { |
||||||
|
return nil, fmt.Errorf("block #%d not found", args.BlockNumber) |
||||||
|
} |
||||||
|
|
||||||
|
stateDb := state.New(block.Root(), self.ethereum.StateDb()) |
||||||
|
if stateDb == nil { |
||||||
|
return nil, nil |
||||||
|
} |
||||||
|
|
||||||
|
return stateDb.Dump(), nil |
||||||
|
} |
||||||
|
|
||||||
|
func (self *DebugApi) GetBlockRlp(req *shared.Request) (interface{}, error) { |
||||||
|
args := new(BlockNumArg) |
||||||
|
if err := self.codec.Decode(req.Params, &args); err != nil { |
||||||
|
return nil, shared.NewDecodeParamError(err.Error()) |
||||||
|
} |
||||||
|
|
||||||
|
block := self.xeth.EthBlockByNumber(args.BlockNumber) |
||||||
|
if block == nil { |
||||||
|
return nil, fmt.Errorf("block #%d not found", args.BlockNumber) |
||||||
|
} |
||||||
|
encoded, err := rlp.EncodeToBytes(block) |
||||||
|
return fmt.Sprintf("%x", encoded), err |
||||||
|
} |
||||||
|
|
||||||
|
func (self *DebugApi) SetHead(req *shared.Request) (interface{}, error) { |
||||||
|
args := new(BlockNumArg) |
||||||
|
if err := self.codec.Decode(req.Params, &args); err != nil { |
||||||
|
return nil, shared.NewDecodeParamError(err.Error()) |
||||||
|
} |
||||||
|
|
||||||
|
block := self.xeth.EthBlockByNumber(args.BlockNumber) |
||||||
|
if block == nil { |
||||||
|
return nil, fmt.Errorf("block #%d not found", args.BlockNumber) |
||||||
|
} |
||||||
|
|
||||||
|
self.ethereum.ChainManager().SetHead(block) |
||||||
|
|
||||||
|
return nil, nil |
||||||
|
} |
||||||
|
|
||||||
|
func (self *DebugApi) ProcessBlock(req *shared.Request) (interface{}, error) { |
||||||
|
args := new(BlockNumArg) |
||||||
|
if err := self.codec.Decode(req.Params, &args); err != nil { |
||||||
|
return nil, shared.NewDecodeParamError(err.Error()) |
||||||
|
} |
||||||
|
|
||||||
|
block := self.xeth.EthBlockByNumber(args.BlockNumber) |
||||||
|
if block == nil { |
||||||
|
return nil, fmt.Errorf("block #%d not found", args.BlockNumber) |
||||||
|
} |
||||||
|
|
||||||
|
old := vm.Debug |
||||||
|
defer func() { vm.Debug = old }() |
||||||
|
vm.Debug = true |
||||||
|
|
||||||
|
_, err := self.ethereum.BlockProcessor().RetryProcess(block) |
||||||
|
if err == nil { |
||||||
|
return true, nil |
||||||
|
} |
||||||
|
return false, err |
||||||
|
} |
||||||
|
|
||||||
|
func (self *DebugApi) SeedHash(req *shared.Request) (interface{}, error) { |
||||||
|
args := new(BlockNumArg) |
||||||
|
if err := self.codec.Decode(req.Params, &args); err != nil { |
||||||
|
return nil, shared.NewDecodeParamError(err.Error()) |
||||||
|
} |
||||||
|
|
||||||
|
if hash, err := ethash.GetSeedHash(uint64(args.BlockNumber)); err == nil { |
||||||
|
return fmt.Sprintf("0x%x", hash), nil |
||||||
|
} else { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
package api |
||||||
|
|
||||||
|
import ( |
||||||
|
"encoding/json" |
||||||
|
"fmt" |
||||||
|
"math/big" |
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/rpc/shared" |
||||||
|
) |
||||||
|
|
||||||
|
type WaitForBlockArgs struct { |
||||||
|
MinHeight int |
||||||
|
Timeout int // in seconds
|
||||||
|
} |
||||||
|
|
||||||
|
func (args *WaitForBlockArgs) UnmarshalJSON(b []byte) (err error) { |
||||||
|
var obj []interface{} |
||||||
|
if err := json.Unmarshal(b, &obj); err != nil { |
||||||
|
return shared.NewDecodeParamError(err.Error()) |
||||||
|
} |
||||||
|
|
||||||
|
if len(obj) > 2 { |
||||||
|
return fmt.Errorf("waitForArgs needs 0, 1, 2 arguments") |
||||||
|
} |
||||||
|
|
||||||
|
// default values when not provided
|
||||||
|
args.MinHeight = -1 |
||||||
|
args.Timeout = -1 |
||||||
|
|
||||||
|
if len(obj) >= 1 { |
||||||
|
var minHeight *big.Int |
||||||
|
if minHeight, err = numString(obj[0]); err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
args.MinHeight = int(minHeight.Int64()) |
||||||
|
} |
||||||
|
|
||||||
|
if len(obj) >= 2 { |
||||||
|
timeout, err := numString(obj[1]) |
||||||
|
if err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
args.Timeout = int(timeout.Int64()) |
||||||
|
} |
||||||
|
|
||||||
|
return nil |
||||||
|
} |
@ -0,0 +1,48 @@ |
|||||||
|
package api |
||||||
|
|
||||||
|
const Debug_JS = ` |
||||||
|
web3.extend({ |
||||||
|
property: 'debug', |
||||||
|
methods: |
||||||
|
[ |
||||||
|
new web3.extend.Method({ |
||||||
|
name: 'printBlock', |
||||||
|
call: 'debug_printBlock', |
||||||
|
params: 1, |
||||||
|
inputFormatter: [web3.extend.formatters.formatInputInt], |
||||||
|
outputFormatter: web3.extend.formatters.formatOutputString |
||||||
|
}), |
||||||
|
new web3.extend.Method({ |
||||||
|
name: 'getBlockRlp', |
||||||
|
call: 'debug_getBlockRlp', |
||||||
|
params: 1, |
||||||
|
inputFormatter: [web3.extend.formatters.formatInputInt], |
||||||
|
outputFormatter: web3.extend.formatters.formatOutputString |
||||||
|
}), |
||||||
|
new web3.extend.Method({ |
||||||
|
name: 'setHead', |
||||||
|
call: 'debug_setHead', |
||||||
|
params: 1, |
||||||
|
inputFormatter: [web3.extend.formatters.formatInputInt], |
||||||
|
outputFormatter: web3.extend.formatters.formatOutputBool |
||||||
|
}), |
||||||
|
new web3.extend.Method({ |
||||||
|
name: 'processBlock', |
||||||
|
call: 'debug_processBlock', |
||||||
|
params: 1, |
||||||
|
inputFormatter: [web3.extend.formatters.formatInputInt], |
||||||
|
outputFormatter: function(obj) { return obj; } |
||||||
|
}), |
||||||
|
new web3.extend.Method({ |
||||||
|
name: 'seedHash', |
||||||
|
call: 'debug_seedHash', |
||||||
|
params: 1, |
||||||
|
inputFormatter: [web3.extend.formatters.formatInputInt], |
||||||
|
outputFormatter: web3.extend.formatters.formatOutputString |
||||||
|
}) |
||||||
|
], |
||||||
|
properties: |
||||||
|
[ |
||||||
|
] |
||||||
|
}); |
||||||
|
` |
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue