aboutsummaryrefslogtreecommitdiffstats
path: root/eth
diff options
context:
space:
mode:
authorFelix Lange <fjl@twurst.com>2015-12-15 18:33:18 +0800
committerFelix Lange <fjl@twurst.com>2015-12-15 18:33:18 +0800
commitb9aedeab0b1cf56860f5ca53333a4f348395259c (patch)
tree3ca53caab0ea965fe322a805f5565e247346cef4 /eth
parent9c636d2490c4f88598752834cc3226902d198ced (diff)
parentd8370a4e15f00afeb783f7f3be8b47e93c4338d2 (diff)
downloaddexon-b9aedeab0b1cf56860f5ca53333a4f348395259c.tar
dexon-b9aedeab0b1cf56860f5ca53333a4f348395259c.tar.gz
dexon-b9aedeab0b1cf56860f5ca53333a4f348395259c.tar.bz2
dexon-b9aedeab0b1cf56860f5ca53333a4f348395259c.tar.lz
dexon-b9aedeab0b1cf56860f5ca53333a4f348395259c.tar.xz
dexon-b9aedeab0b1cf56860f5ca53333a4f348395259c.tar.zst
dexon-b9aedeab0b1cf56860f5ca53333a4f348395259c.zip
Merge pull request #2072 from karalabe/admin-debug-apis
core, eth, node, rpc: port the admin and debug API
Diffstat (limited to 'eth')
-rw-r--r--eth/api.go217
-rw-r--r--eth/backend.go13
2 files changed, 215 insertions, 15 deletions
diff --git a/eth/api.go b/eth/api.go
index 06fc2deb1..068b350db 100644
--- a/eth/api.go
+++ b/eth/api.go
@@ -21,7 +21,9 @@ import (
"encoding/json"
"errors"
"fmt"
+ "io"
"math/big"
+ "os"
"sync"
"time"
@@ -46,7 +48,7 @@ import (
const (
defaultGasPrice = uint64(10000000000000)
- defaultGas = uint64(90000)
+ defaultGas = uint64(90000)
)
// PublicEthereumAPI provides an API to access Ethereum related information.
@@ -471,12 +473,12 @@ type callmsg struct {
// accessor boilerplate to implement core.Message
func (m callmsg) From() (common.Address, error) { return m.from.Address(), nil }
-func (m callmsg) Nonce() uint64 { return m.from.Nonce() }
-func (m callmsg) To() *common.Address { return m.to }
-func (m callmsg) GasPrice() *big.Int { return m.gasPrice }
-func (m callmsg) Gas() *big.Int { return m.gas }
-func (m callmsg) Value() *big.Int { return m.value }
-func (m callmsg) Data() []byte { return m.data }
+func (m callmsg) Nonce() uint64 { return m.from.Nonce() }
+func (m callmsg) To() *common.Address { return m.to }
+func (m callmsg) GasPrice() *big.Int { return m.gasPrice }
+func (m callmsg) Gas() *big.Int { return m.gas }
+func (m callmsg) Value() *big.Int { return m.value }
+func (m callmsg) Data() []byte { return m.data }
type CallArgs struct {
From common.Address `json:"from"`
@@ -972,20 +974,20 @@ func (s *PublicTransactionPoolAPI) Sign(address common.Address, data string) (st
}
type SignTransactionArgs struct {
- From common.Address
- To common.Address
- Nonce *rpc.HexNumber
- Value *rpc.HexNumber
- Gas *rpc.HexNumber
- GasPrice *rpc.HexNumber
- Data string
+ From common.Address
+ To common.Address
+ Nonce *rpc.HexNumber
+ Value *rpc.HexNumber
+ Gas *rpc.HexNumber
+ GasPrice *rpc.HexNumber
+ Data string
BlockNumber int64
}
// Tx is a helper object for argument and return values
type Tx struct {
- tx *types.Transaction
+ tx *types.Transaction
To *common.Address `json:"to"`
From common.Address `json:"from"`
@@ -1214,3 +1216,188 @@ func (s *PublicTransactionPoolAPI) Resend(tx *Tx, gasPrice, gasLimit *rpc.HexNum
return common.Hash{}, fmt.Errorf("Transaction %#x not found", tx.Hash)
}
+
+// PrivateAdminAPI is the collection of Etheruem APIs exposed over the private
+// admin endpoint.
+type PrivateAdminAPI struct {
+ eth *Ethereum
+}
+
+// NewPrivateAdminAPI creates a new API definition for the private admin methods
+// of the Ethereum service.
+func NewPrivateAdminAPI(eth *Ethereum) *PrivateAdminAPI {
+ return &PrivateAdminAPI{eth: eth}
+}
+
+// SetSolc sets the Solidity compiler path to be used by the node.
+func (api *PrivateAdminAPI) SetSolc(path string) (string, error) {
+ solc, err := api.eth.SetSolc(path)
+ if err != nil {
+ return "", err
+ }
+ return solc.Info(), nil
+}
+
+// ExportChain exports the current blockchain into a local file.
+func (api *PrivateAdminAPI) ExportChain(file string) (bool, error) {
+ // Make sure we can create the file to export into
+ out, err := os.OpenFile(file, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
+ if err != nil {
+ return false, err
+ }
+ defer out.Close()
+
+ // Export the blockchain
+ if err := api.eth.BlockChain().Export(out); err != nil {
+ return false, err
+ }
+ return true, nil
+}
+
+// ImportChain imports a blockchain from a local file.
+func (api *PrivateAdminAPI) ImportChain(file string) (bool, error) {
+ // Make sure the can access the file to import
+ in, err := os.Open(file)
+ if err != nil {
+ return false, err
+ }
+ defer in.Close()
+
+ // Run actual the import in pre-configured batches
+ stream := rlp.NewStream(in, 0)
+
+ blocks, index := make([]*types.Block, 0, 2500), 0
+ for batch := 0; ; batch++ {
+ // Load a batch of blocks from the input file
+ for len(blocks) < cap(blocks) {
+ block := new(types.Block)
+ if err := stream.Decode(block); err == io.EOF {
+ break
+ } else if err != nil {
+ return false, fmt.Errorf("block %d: failed to parse: %v", index, err)
+ }
+ blocks = append(blocks, block)
+ index++
+ }
+ if len(blocks) == 0 {
+ break
+ }
+ // Import the batch and reset the buffer
+ if _, err := api.eth.BlockChain().InsertChain(blocks); err != nil {
+ return false, fmt.Errorf("batch %d: failed to insert: %v", batch, err)
+ }
+ blocks = blocks[:0]
+ }
+ return true, nil
+}
+
+// PublicDebugAPI is the collection of Etheruem APIs exposed over the public
+// debugging endpoint.
+type PublicDebugAPI struct {
+ eth *Ethereum
+}
+
+// NewPublicDebugAPI creates a new API definition for the public debug methods
+// of the Ethereum service.
+func NewPublicDebugAPI(eth *Ethereum) *PublicDebugAPI {
+ return &PublicDebugAPI{eth: eth}
+}
+
+// DumpBlock retrieves the entire state of the database at a given block.
+func (api *PublicDebugAPI) DumpBlock(number uint64) (state.World, error) {
+ block := api.eth.BlockChain().GetBlockByNumber(number)
+ if block == nil {
+ return state.World{}, fmt.Errorf("block #%d not found", number)
+ }
+ stateDb, err := state.New(block.Root(), api.eth.ChainDb())
+ if err != nil {
+ return state.World{}, err
+ }
+ return stateDb.RawDump(), nil
+}
+
+// GetBlockRlp retrieves the RLP encoded for of a single block.
+func (api *PublicDebugAPI) GetBlockRlp(number uint64) (string, error) {
+ block := api.eth.BlockChain().GetBlockByNumber(number)
+ if block == nil {
+ return "", fmt.Errorf("block #%d not found", number)
+ }
+ encoded, err := rlp.EncodeToBytes(block)
+ if err != nil {
+ return "", err
+ }
+ return fmt.Sprintf("%x", encoded), nil
+}
+
+// PrintBlock retrieves a block and returns its pretty printed form.
+func (api *PublicDebugAPI) PrintBlock(number uint64) (string, error) {
+ block := api.eth.BlockChain().GetBlockByNumber(number)
+ if block == nil {
+ return "", fmt.Errorf("block #%d not found", number)
+ }
+ return fmt.Sprintf("%s", block), nil
+}
+
+// SeedHash retrieves the seed hash of a block.
+func (api *PublicDebugAPI) SeedHash(number uint64) (string, error) {
+ block := api.eth.BlockChain().GetBlockByNumber(number)
+ if block == nil {
+ return "", fmt.Errorf("block #%d not found", number)
+ }
+ hash, err := ethash.GetSeedHash(number)
+ if err != nil {
+ return "", err
+ }
+ return fmt.Sprintf("0x%x", hash), nil
+}
+
+// PrivateDebugAPI is the collection of Etheruem APIs exposed over the private
+// debugging endpoint.
+type PrivateDebugAPI struct {
+ eth *Ethereum
+}
+
+// NewPrivateDebugAPI creates a new API definition for the private debug methods
+// of the Ethereum service.
+func NewPrivateDebugAPI(eth *Ethereum) *PrivateDebugAPI {
+ return &PrivateDebugAPI{eth: eth}
+}
+
+// ProcessBlock reprocesses an already owned block.
+func (api *PrivateDebugAPI) ProcessBlock(number uint64) (bool, error) {
+ // Fetch the block that we aim to reprocess
+ block := api.eth.BlockChain().GetBlockByNumber(number)
+ if block == nil {
+ return false, fmt.Errorf("block #%d not found", number)
+ }
+ // Temporarily enable debugging
+ defer func(old bool) { vm.Debug = old }(vm.Debug)
+ vm.Debug = true
+
+ // Validate and reprocess the block
+ var (
+ blockchain = api.eth.BlockChain()
+ validator = blockchain.Validator()
+ processor = blockchain.Processor()
+ )
+ if err := core.ValidateHeader(blockchain.AuxValidator(), block.Header(), blockchain.GetHeader(block.ParentHash()), true, false); err != nil {
+ return false, err
+ }
+ statedb, err := state.New(blockchain.GetBlock(block.ParentHash()).Root(), api.eth.ChainDb())
+ if err != nil {
+ return false, err
+ }
+ receipts, _, usedGas, err := processor.Process(block, statedb)
+ if err != nil {
+ return false, err
+ }
+ if err := validator.ValidateState(block, blockchain.GetBlock(block.ParentHash()), statedb, receipts, usedGas); err != nil {
+ return false, err
+ }
+ return true, nil
+}
+
+// SetHead rewinds the head of the blockchain to a previous block.
+func (api *PrivateDebugAPI) SetHead(number uint64) {
+ api.eth.BlockChain().SetHead(number)
+}
diff --git a/eth/backend.go b/eth/backend.go
index ad98635a5..d51446d51 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -295,6 +295,19 @@ func (s *Ethereum) APIs() []rpc.API {
Version: "1.0",
Service: filters.NewPublicFilterAPI(s.ChainDb(), s.EventMux()),
Public: true,
+ }, {
+ Namespace: "admin",
+ Version: "1.0",
+ Service: NewPrivateAdminAPI(s),
+ }, {
+ Namespace: "debug",
+ Version: "1.0",
+ Service: NewPublicDebugAPI(s),
+ Public: true,
+ }, {
+ Namespace: "debug",
+ Version: "1.0",
+ Service: NewPrivateDebugAPI(s),
},
}
}