aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/geth/main.go30
-rw-r--r--eth/backend.go9
-rw-r--r--jsre/ethereum_js.go4
-rw-r--r--miner/miner.go20
-rw-r--r--miner/remote_agent.go37
-rw-r--r--rpc/api/eth.go10
-rw-r--r--rpc/api/eth_args.go31
-rw-r--r--rpc/api/miner.go8
-rw-r--r--xeth/xeth.go11
-rw-r--r--xeth/xeth_test.go26
10 files changed, 165 insertions, 21 deletions
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index 68c66a4ab..0e73822f3 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -42,6 +42,8 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/metrics"
+ "github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/comms"
"github.com/mattn/go-colorable"
@@ -49,8 +51,11 @@ import (
)
const (
- ClientIdentifier = "Geth"
+ ClientIdentifier = "Geth "
Version = "1.0.1"
+ VersionMajor = 1
+ VersionMinor = 0
+ VersionPatch = 1
)
var (
@@ -349,6 +354,27 @@ func main() {
}
}
+func makeDefaultExtra() []byte {
+ var clientInfo = struct {
+ Version uint
+ Name string
+ GoVersion string
+ Os string
+ }{uint(VersionMajor<<16 | VersionMinor<<8 | VersionPatch), ClientIdentifier, runtime.Version(), runtime.GOOS}
+ extra, err := rlp.EncodeToBytes(clientInfo)
+ if err != nil {
+ glog.V(logger.Warn).Infoln("error setting canonical miner information:", err)
+ }
+
+ if uint64(len(extra)) > params.MaximumExtraDataSize.Uint64() {
+ glog.V(logger.Warn).Infoln("error setting canonical miner information: extra exceeds", params.MaximumExtraDataSize)
+ glog.V(logger.Debug).Infof("extra: %x\n", extra)
+ return nil
+ }
+
+ return extra
+}
+
func run(ctx *cli.Context) {
utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
if ctx.GlobalBool(utils.OlympicFlag.Name) {
@@ -356,6 +382,8 @@ func run(ctx *cli.Context) {
}
cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
+ cfg.ExtraData = makeDefaultExtra()
+
ethereum, err := eth.New(cfg)
if err != nil {
utils.Fatalf("%v", err)
diff --git a/eth/backend.go b/eth/backend.go
index 4795000e0..ed46a4ab3 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -45,7 +45,6 @@ import (
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/p2p/nat"
- "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/whisper"
)
@@ -92,6 +91,7 @@ type Config struct {
NatSpec bool
AutoDAG bool
PowTest bool
+ ExtraData []byte
MaxPeers int
MaxPendingPeers int
@@ -378,12 +378,7 @@ func New(config *Config) (*Ethereum, error) {
eth.miner = miner.New(eth, eth.EventMux(), eth.pow)
eth.miner.SetGasPrice(config.GasPrice)
-
- extra := config.Name
- if uint64(len(extra)) > params.MaximumExtraDataSize.Uint64() {
- extra = extra[:params.MaximumExtraDataSize.Uint64()]
- }
- eth.miner.SetExtra([]byte(extra))
+ eth.miner.SetExtra(config.ExtraData)
if config.Shh {
eth.whisper = whisper.New()
diff --git a/jsre/ethereum_js.go b/jsre/ethereum_js.go
index 27dbed24c..012e5af70 100644
--- a/jsre/ethereum_js.go
+++ b/jsre/ethereum_js.go
@@ -1137,10 +1137,10 @@ var toHex = function (val) {
if (isString(val)) {
if (val.indexOf('-0x') === 0)
return fromDecimal(val);
- else if (!isFinite(val))
- return fromAscii(val);
else if(val.indexOf('0x') === 0)
return val;
+ else if (!isFinite(val))
+ return fromAscii(val);
}
return fromDecimal(val);
diff --git a/miner/miner.go b/miner/miner.go
index bf6a48802..b550ed6d6 100644
--- a/miner/miner.go
+++ b/miner/miner.go
@@ -18,6 +18,7 @@
package miner
import (
+ "fmt"
"math/big"
"sync/atomic"
@@ -29,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
+ "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
)
@@ -139,12 +141,24 @@ func (self *Miner) Mining() bool {
return atomic.LoadInt32(&self.mining) > 0
}
-func (self *Miner) HashRate() int64 {
- return self.pow.GetHashrate()
+func (self *Miner) HashRate() (tot int64) {
+ tot += self.pow.GetHashrate()
+ // do we care this might race? is it worth we're rewriting some
+ // aspects of the worker/locking up agents so we can get an accurate
+ // hashrate?
+ for _, agent := range self.worker.agents {
+ tot += agent.GetHashRate()
+ }
+ return
}
-func (self *Miner) SetExtra(extra []byte) {
+func (self *Miner) SetExtra(extra []byte) error {
+ if uint64(len(extra)) > params.MaximumExtraDataSize.Uint64() {
+ return fmt.Errorf("Extra exceeds max length. %d > %v", len(extra), params.MaximumExtraDataSize)
+ }
+
self.worker.extra = extra
+ return nil
}
func (self *Miner) PendingState() *state.StateDB {
diff --git a/miner/remote_agent.go b/miner/remote_agent.go
index 674ca40ac..5c672a6e0 100644
--- a/miner/remote_agent.go
+++ b/miner/remote_agent.go
@@ -27,6 +27,11 @@ import (
"github.com/ethereum/go-ethereum/logger/glog"
)
+type hashrate struct {
+ ping time.Time
+ rate uint64
+}
+
type RemoteAgent struct {
mu sync.Mutex
@@ -36,14 +41,24 @@ type RemoteAgent struct {
currentWork *Work
work map[common.Hash]*Work
+
+ hashrateMu sync.RWMutex
+ hashrate map[common.Hash]hashrate
}
func NewRemoteAgent() *RemoteAgent {
- agent := &RemoteAgent{work: make(map[common.Hash]*Work)}
+ agent := &RemoteAgent{work: make(map[common.Hash]*Work), hashrate: make(map[common.Hash]hashrate)}
return agent
}
+func (a *RemoteAgent) SubmitHashrate(id common.Hash, rate uint64) {
+ a.hashrateMu.Lock()
+ defer a.hashrateMu.Unlock()
+
+ a.hashrate[id] = hashrate{time.Now(), rate}
+}
+
func (a *RemoteAgent) Work() chan<- *Work {
return a.workCh
}
@@ -63,7 +78,17 @@ func (a *RemoteAgent) Stop() {
close(a.workCh)
}
-func (a *RemoteAgent) GetHashRate() int64 { return 0 }
+// GetHashRate returns the accumulated hashrate of all identifier combined
+func (a *RemoteAgent) GetHashRate() (tot int64) {
+ a.hashrateMu.RLock()
+ defer a.hashrateMu.RUnlock()
+
+ // this could overflow
+ for _, hashrate := range a.hashrate {
+ tot += int64(hashrate.rate)
+ }
+ return
+}
func (a *RemoteAgent) GetWork() [3]string {
a.mu.Lock()
@@ -131,6 +156,14 @@ out:
}
}
a.mu.Unlock()
+
+ a.hashrateMu.Lock()
+ for id, hashrate := range a.hashrate {
+ if time.Since(hashrate.ping) > 10*time.Second {
+ delete(a.hashrate, id)
+ }
+ }
+ a.hashrateMu.Unlock()
}
}
}
diff --git a/rpc/api/eth.go b/rpc/api/eth.go
index 4041811f0..820ea761b 100644
--- a/rpc/api/eth.go
+++ b/rpc/api/eth.go
@@ -92,6 +92,7 @@ var (
"eth_hashrate": (*ethApi).Hashrate,
"eth_getWork": (*ethApi).GetWork,
"eth_submitWork": (*ethApi).SubmitWork,
+ "eth_submitHashrate": (*ethApi).SubmitHashrate,
"eth_resend": (*ethApi).Resend,
"eth_pendingTransactions": (*ethApi).PendingTransactions,
"eth_getTransactionReceipt": (*ethApi).GetTransactionReceipt,
@@ -573,6 +574,15 @@ func (self *ethApi) SubmitWork(req *shared.Request) (interface{}, error) {
return self.xeth.RemoteMining().SubmitWork(args.Nonce, common.HexToHash(args.Digest), common.HexToHash(args.Header)), nil
}
+func (self *ethApi) SubmitHashrate(req *shared.Request) (interface{}, error) {
+ args := new(SubmitHashRateArgs)
+ if err := self.codec.Decode(req.Params, &args); err != nil {
+ return nil, shared.NewDecodeParamError(err.Error())
+ }
+ self.xeth.RemoteMining().SubmitHashrate(common.HexToHash(args.Id), args.Rate)
+ return nil, nil
+}
+
func (self *ethApi) Resend(req *shared.Request) (interface{}, error) {
args := new(ResendArgs)
if err := self.codec.Decode(req.Params, &args); err != nil {
diff --git a/rpc/api/eth_args.go b/rpc/api/eth_args.go
index 1218bd625..5a1841cbe 100644
--- a/rpc/api/eth_args.go
+++ b/rpc/api/eth_args.go
@@ -169,6 +169,37 @@ func (args *GetTxCountArgs) UnmarshalJSON(b []byte) (err error) {
return nil
}
+type SubmitHashRateArgs struct {
+ Id string
+ Rate uint64
+}
+
+func (args *SubmitHashRateArgs) 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 shared.NewInsufficientParamsError(len(obj), 2)
+ }
+
+ arg0, ok := obj[0].(string)
+ if !ok {
+ return shared.NewInvalidTypeError("hash", "not a string")
+ }
+ args.Id = arg0
+
+ arg1, ok := obj[1].(string)
+ if !ok {
+ return shared.NewInvalidTypeError("rate", "not a string")
+ }
+
+ args.Rate = common.String2Big(arg1).Uint64()
+
+ return nil
+}
+
type HashArgs struct {
Hash string
}
diff --git a/rpc/api/miner.go b/rpc/api/miner.go
index 3c3d1ee0b..5325a660a 100644
--- a/rpc/api/miner.go
+++ b/rpc/api/miner.go
@@ -17,12 +17,9 @@
package api
import (
- "fmt"
-
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/shared"
)
@@ -126,11 +123,10 @@ func (self *minerApi) SetExtra(req *shared.Request) (interface{}, error) {
return nil, err
}
- if uint64(len(args.Data)) > params.MaximumExtraDataSize.Uint64()*2 {
- return false, fmt.Errorf("extra datasize can be no longer than %v bytes", params.MaximumExtraDataSize)
+ if err := self.ethereum.Miner().SetExtra([]byte(args.Data)); err != nil {
+ return false, err
}
- self.ethereum.Miner().SetExtra([]byte(args.Data))
return true, nil
}
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 5d54c1f7e..f447a1ac3 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -20,8 +20,10 @@ package xeth
import (
"bytes"
"encoding/json"
+ "errors"
"fmt"
"math/big"
+ "regexp"
"sync"
"time"
@@ -45,6 +47,7 @@ var (
defaultGasPrice = big.NewInt(10000000000000) //150000000000
defaultGas = big.NewInt(90000) //500000
dappStorePre = []byte("dapp-")
+ addrReg = regexp.MustCompile(`^(0x)?[a-fA-F0-9]{40}$`)
)
// byte will be inferred
@@ -878,6 +881,10 @@ func (self *XEth) Sign(fromStr, hashStr string, didUnlock bool) (string, error)
return common.ToHex(sig), nil
}
+func isAddress(addr string) bool {
+ return addrReg.MatchString(addr)
+}
+
func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
// this minimalistic recoding is enough (works for natspec.js)
@@ -887,6 +894,10 @@ func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceS
return "", err
}
+ if len(toStr) > 0 && toStr != "0x" && !isAddress(toStr) {
+ return "", errors.New("Invalid address")
+ }
+
var (
from = common.HexToAddress(fromStr)
to = common.HexToAddress(toStr)
diff --git a/xeth/xeth_test.go b/xeth/xeth_test.go
new file mode 100644
index 000000000..e649d20ef
--- /dev/null
+++ b/xeth/xeth_test.go
@@ -0,0 +1,26 @@
+package xeth
+
+import "testing"
+
+func TestIsAddress(t *testing.T) {
+ for _, invalid := range []string{
+ "0x00",
+ "0xNN",
+ "0x00000000000000000000000000000000000000NN",
+ "0xAAar000000000000000000000000000000000000",
+ } {
+ if isAddress(invalid) {
+ t.Error("Expected", invalid, "to be invalid")
+ }
+ }
+
+ for _, valid := range []string{
+ "0x0000000000000000000000000000000000000000",
+ "0xAABBbbCCccff9900000000000000000000000000",
+ "AABBbbCCccff9900000000000000000000000000",
+ } {
+ if !isAddress(valid) {
+ t.Error("Expected", valid, "to be valid")
+ }
+ }
+}