added miner API

This commit is contained in:
Bas van Kervel 2015-06-08 14:42:15 +02:00 committed by Bas van Kervel
parent cb7f2d43b6
commit 4b9b633dfe
5 changed files with 323 additions and 1 deletions

@ -4,10 +4,11 @@ import "github.com/ethereum/go-ethereum/rpc/shared"
const (
// List with all API's which are offered over the IPC interface by default
DefaultIpcApis = "eth,web3"
DefaultIpcApis = "eth,web3,miner"
EthApiName = "eth"
MergedApiName = "merged"
MinerApiName = "miner"
Web3ApiName = "web3"
)

143
rpc/api/miner.go Normal file

@ -0,0 +1,143 @@
package api
import (
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/shared"
)
const (
MinerVersion = "1.0.0"
)
var (
// mapping between methods and handlers
MinerMapping = map[string]minerhandler{
"miner_hashrate": (*miner).Hashrate,
"miner_makeDAG": (*miner).MakeDAG,
"miner_setExtra": (*miner).SetExtra,
"miner_setGasPrice": (*miner).SetGasPrice,
"miner_startAutoDAG": (*miner).StartAutoDAG,
"miner_start": (*miner).StartMiner,
"miner_stopAutoDAG": (*miner).StopAutoDAG,
"miner_stop": (*miner).StopMiner,
}
)
// miner callback handler
type minerhandler func(*miner, *shared.Request) (interface{}, error)
// miner api provider
type miner struct {
ethereum *eth.Ethereum
methods map[string]minerhandler
codec codec.ApiCoder
}
// create a new miner api instance
func NewMinerApi(ethereum *eth.Ethereum, coder codec.Codec) *miner {
return &miner{
ethereum: ethereum,
methods: MinerMapping,
codec: coder.New(nil),
}
}
// Execute given request
func (self *miner) Execute(req *shared.Request) (interface{}, error) {
if callback, ok := self.methods[req.Method]; ok {
return callback(self, req)
}
return nil, &shared.NotImplementedError{req.Method}
}
// collection with supported methods
func (self *miner) Methods() []string {
methods := make([]string, len(self.methods))
i := 0
for k := range self.methods {
methods[i] = k
i++
}
return methods
}
func (self *miner) Name() string {
return MinerApiName
}
func (self *miner) StartMiner(req *shared.Request) (interface{}, error) {
args := new(StartMinerArgs)
if err := self.codec.Decode(req.Params, &args); err != nil {
return nil, err
}
if args.Threads == -1 { // (not specified by user, use default)
args.Threads = self.ethereum.MinerThreads
}
self.ethereum.StartAutoDAG()
err := self.ethereum.StartMining(args.Threads)
if err == nil {
return true, nil
}
return false, err
}
func (self *miner) StopMiner(req *shared.Request) (interface{}, error) {
self.ethereum.StopMining()
return true, nil
}
func (self *miner) Hashrate(req *shared.Request) (interface{}, error) {
return self.ethereum.Miner().HashRate(), nil
}
func (self *miner) SetExtra(req *shared.Request) (interface{}, error) {
args := new(SetExtraArgs)
if err := self.codec.Decode(req.Params, &args); err != nil {
return nil, err
}
self.ethereum.Miner().SetExtra([]byte(args.Data))
return true, nil
}
func (self *miner) SetGasPrice(req *shared.Request) (interface{}, error) {
args := new(GasPriceArgs)
if err := self.codec.Decode(req.Params, &args); err != nil {
return false, err
}
self.ethereum.Miner().SetGasPrice(common.String2Big(args.Price))
return true, nil
}
func (self *miner) StartAutoDAG(req *shared.Request) (interface{}, error) {
self.ethereum.StartAutoDAG()
return true, nil
}
func (self *miner) StopAutoDAG(req *shared.Request) (interface{}, error) {
self.ethereum.StopAutoDAG()
return true, nil
}
func (self *miner) MakeDAG(req *shared.Request) (interface{}, error) {
args := new(MakeDAGArgs)
if err := self.codec.Decode(req.Params, &args); err != nil {
return nil, err
}
if args.BlockNumber < 0 {
return false, shared.NewValidationError("BlockNumber", "BlockNumber must be positive")
}
err := ethash.MakeDAG(uint64(args.BlockNumber), "")
if err == nil {
return true, nil
}
return false, err
}

93
rpc/api/miner_args.go Normal file

@ -0,0 +1,93 @@
package api
import (
"encoding/json"
"math/big"
"github.com/ethereum/go-ethereum/rpc/shared"
)
type StartMinerArgs struct {
Threads int
}
func (args *StartMinerArgs) UnmarshalJSON(b []byte) (err error) {
var obj []interface{}
if err := json.Unmarshal(b, &obj); err != nil {
return shared.NewDecodeParamError(err.Error())
}
if len(obj) == 0 || obj[0] == nil {
args.Threads = -1
return nil
}
var num *big.Int
if num, err = numString(obj[0]); err != nil {
return err
}
args.Threads = int(num.Int64())
return nil
}
type SetExtraArgs struct {
Data string
}
func (args *SetExtraArgs) UnmarshalJSON(b []byte) (err error) {
var obj []interface{}
if err := json.Unmarshal(b, &obj); err != nil {
return shared.NewDecodeParamError(err.Error())
}
extrastr, ok := obj[0].(string)
if !ok {
return shared.NewInvalidTypeError("Price", "not a string")
}
args.Data = extrastr
return nil
}
type GasPriceArgs struct {
Price string
}
func (args *GasPriceArgs) UnmarshalJSON(b []byte) (err error) {
var obj []interface{}
if err := json.Unmarshal(b, &obj); err != nil {
return shared.NewDecodeParamError(err.Error())
}
pricestr, ok := obj[0].(string)
if !ok {
return shared.NewInvalidTypeError("Price", "not a string")
}
args.Price = pricestr
return nil
}
type MakeDAGArgs struct {
BlockNumber int64
}
func (args *MakeDAGArgs) UnmarshalJSON(b []byte) (err error) {
args.BlockNumber = -1
var obj []interface{}
if err := json.Unmarshal(b, &obj); err != nil {
return shared.NewDecodeParamError(err.Error())
}
if len(obj) < 1 {
return shared.NewInsufficientParamsError(len(obj), 1)
}
if err := blockHeight(obj[0], &args.BlockNumber); err != nil {
return err
}
return nil
}

74
rpc/api/miner_js.go Normal file

@ -0,0 +1,74 @@
package api
const Miner_JS = `
web3.extend({
property: 'miner',
methods:
[
new web3.extend.Method({
name: 'start',
call: 'miner_start',
params: 1,
inputFormatter: [web3.extend.formatters.formatInputInt],
outputFormatter: web3.extend.formatters.formatOutputBool
}),
new web3.extend.Method({
name: 'stop',
call: 'miner_stop',
params: 1,
inputFormatter: [web3.extend.formatters.formatInputInt],
outputFormatter: web3.extend.formatters.formatOutputBool
}),
new web3.extend.Method({
name: 'getHashrate',
call: 'miner_hashrate',
params: 0,
inputFormatter: [],
outputFormatter: web3.extend.utils.toDecimal
}),
new web3.extend.Method({
name: 'setExtra',
call: 'miner_setExtra',
params: 1,
inputFormatter: [web3.extend.utils.formatInputString],
outputFormatter: web3.extend.formatters.formatOutputBool
}),
new web3.extend.Method({
name: 'setGasPrice',
call: 'miner_setGasPrice',
params: 1,
inputFormatter: [web3.extend.utils.formatInputString],
outputFormatter: web3.extend.formatters.formatOutputBool
}),
new web3.extend.Method({
name: 'startAutoDAG',
call: 'miner_startAutoDAG',
params: 0,
inputFormatter: [],
outputFormatter: web3.extend.formatters.formatOutputBool
}),
new web3.extend.Method({
name: 'stopAutoDAG',
call: 'miner_stopAutoDAG',
params: 0,
inputFormatter: [],
outputFormatter: web3.extend.formatters.formatOutputBool
}),
new web3.extend.Method({
name: 'makeDAG',
call: 'miner_makeDAG',
params: 1,
inputFormatter: [web3.extend.formatters.inputDefaultBlockNumberFormatter],
outputFormatter: web3.extend.formatters.formatOutputBool
})
],
properties:
[
new web3.extend.Property({
name: 'hashrate',
getter: 'miner_hashrate',
outputFormatter: web3.extend.utils.toDecimal
})
]
});
`

@ -23,6 +23,8 @@ func ParseApiString(apistr string, codec codec.Codec, xeth *xeth.XEth, eth *eth.
switch strings.ToLower(strings.TrimSpace(name)) {
case EthApiName:
apis[i] = NewEthApi(xeth, codec)
case MinerApiName:
apis[i] = NewMinerApi(eth, codec)
case Web3ApiName:
apis[i] = NewWeb3(xeth, codec)
default:
@ -32,3 +34,12 @@ func ParseApiString(apistr string, codec codec.Codec, xeth *xeth.XEth, eth *eth.
return apis, nil
}
func Javascript(name string) string {
switch strings.ToLower(strings.TrimSpace(name)) {
case MinerApiName:
return Miner_JS
}
return ""
}