Merge remote-tracking branch 'upstream/develop' into blockpool2

This commit is contained in:
zelig 2015-03-03 02:13:41 +07:00
commit af6971f823
41 changed files with 1073 additions and 665 deletions

View File

@ -1,8 +1,8 @@
language: go
go:
- 1.4.1
- 1.4.2
before_install:
- sudo add-apt-repository ppa:beineri/opt-qt54 -y
- sudo add-apt-repository ppa:beineri/opt-qt541 -y
- sudo apt-get update -qq
- sudo apt-get install -yqq libgmp3-dev libreadline6-dev qt54quickcontrols qt54webengine
install:

View File

@ -1,4 +1,4 @@
FROM ubuntu:14.04.1
FROM ubuntu:14.04.2
## Environment setup
ENV HOME /root
@ -12,22 +12,22 @@ ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update && apt-get upgrade -y
RUN apt-get install -y git mercurial build-essential software-properties-common wget pkg-config libgmp3-dev libreadline6-dev libpcre3-dev libpcre++-dev
## Install Qt5.4 (not required for CLI)
# RUN add-apt-repository ppa:beineri/opt-qt54-trusty -y
## Install Qt5.4.1 (not required for CLI)
# RUN add-apt-repository ppa:beineri/opt-qt541-trusty -y
# RUN apt-get update -y
# RUN apt-get install -y qt54quickcontrols qt54webengine mesa-common-dev libglu1-mesa-dev
# ENV PKG_CONFIG_PATH /opt/qt54/lib/pkgconfig
# Install Golang
RUN wget https://storage.googleapis.com/golang/go1.4.1.linux-amd64.tar.gz
RUN wget https://storage.googleapis.com/golang/go1.4.2.linux-amd64.tar.gz
RUN tar -C /usr/local -xzf go*.tar.gz && go version
# this is a workaround, to make sure that docker's cache is invalidated whenever the git repo changes
ADD https://api.github.com/repos/ethereum/go-ethereum/git/refs/heads/develop file_does_not_exist
## Fetch and install go-ethereum
RUN go get -v github.com/tools/godep
RUN go get -v -d github.com/ethereum/go-ethereum/...
RUN go get github.com/tools/godep
RUN go get -d github.com/ethereum/go-ethereum/...
WORKDIR $GOPATH/src/github.com/ethereum/go-ethereum
RUN git checkout develop
RUN godep restore

11
Godeps/Godeps.json generated
View File

@ -1,15 +1,10 @@
{
"ImportPath": "github.com/ethereum/go-ethereum",
"GoVersion": "go1.4.1",
"GoVersion": "go1.4.2",
"Packages": [
"./..."
],
"Deps": [
{
"ImportPath": "bitbucket.org/kardianos/osext",
"Comment": "null-13",
"Rev": "5d3ddcf53a508cc2f7404eaebf546ef2cb5cdb6e"
},
{
"ImportPath": "code.google.com/p/go-uuid/uuid",
"Comment": "null-12",
@ -37,6 +32,10 @@
"ImportPath": "github.com/jackpal/go-nat-pmp",
"Rev": "a45aa3d54aef73b504e15eb71bea0e5565b5e6e1"
},
{
"ImportPath": "github.com/kardianos/osext",
"Rev": "ccfcd0245381f0c94c68f50626665eed3c6b726a"
},
{
"ImportPath": "github.com/obscuren/otto",
"Rev": "cf13cc4228c5e5ce0fe27a7aea90bc10091c4f19"

View File

@ -1,20 +0,0 @@
Copyright (c) 2012 Daniel Theophanes
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.

View File

@ -0,0 +1,27 @@
Copyright (c) 2012 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,14 @@
### Extensions to the "os" package.
## Find the current Executable and ExecutableFolder.
There is sometimes utility in finding the current executable file
that is running. This can be used for upgrading the current executable
or finding resources located relative to the executable file.
Multi-platform and supports:
* Linux
* OS X
* Windows
* Plan 9
* BSDs.

View File

@ -25,8 +25,3 @@ func ExecutableFolder() (string, error) {
folder, _ := filepath.Split(p)
return folder, nil
}
// Depricated. Same as Executable().
func GetExePath() (exePath string, err error) {
return Executable()
}

View File

@ -5,16 +5,16 @@
package osext
import (
"syscall"
"os"
"strconv"
"os"
"strconv"
"syscall"
)
func executable() (string, error) {
f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text")
if err != nil {
return "", err
}
defer f.Close()
return syscall.Fd2path(int(f.Fd()))
f, err := os.Open("/proc/" + strconv.Itoa(os.Getpid()) + "/text")
if err != nil {
return "", err
}
defer f.Close()
return syscall.Fd2path(int(f.Fd()))
}

View File

@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux netbsd openbsd
// +build linux netbsd openbsd solaris dragonfly
package osext
import (
"errors"
"fmt"
"os"
"runtime"
)
@ -18,8 +19,10 @@ func executable() (string, error) {
return os.Readlink("/proc/self/exe")
case "netbsd":
return os.Readlink("/proc/curproc/exe")
case "openbsd":
case "openbsd", "dragonfly":
return os.Readlink("/proc/curproc/file")
case "solaris":
return os.Readlink(fmt.Sprintf("/proc/%d/path/a.out", os.Getpid()))
}
return "", errors.New("ExecPath not implemented for " + runtime.GOOS)
}

View File

@ -34,24 +34,34 @@ package accounts
import (
crand "crypto/rand"
"errors"
"sync"
"time"
"github.com/ethereum/go-ethereum/crypto"
)
var ErrLocked = errors.New("account is locked; please request passphrase")
// TODO: better name for this struct?
type Account struct {
Address []byte
}
type AccountManager struct {
keyStore crypto.KeyStore2
keyStore crypto.KeyStore2
unlockedKeys map[string]crypto.Key
unlockMilliseconds time.Duration
mutex sync.RWMutex
}
// TODO: get key by addr - modify KeyStore2 GetKey to work with addr
// TODO: pass through passphrase for APIs which require access to private key?
func NewAccountManager(keyStore crypto.KeyStore2) AccountManager {
func NewAccountManager(keyStore crypto.KeyStore2, unlockMilliseconds time.Duration) AccountManager {
keysMap := make(map[string]crypto.Key)
am := &AccountManager{
keyStore: keyStore,
keyStore: keyStore,
unlockedKeys: keysMap,
unlockMilliseconds: unlockMilliseconds,
}
return *am
}
@ -60,11 +70,26 @@ func (am AccountManager) DeleteAccount(address []byte, auth string) error {
return am.keyStore.DeleteKey(address, auth)
}
func (am *AccountManager) Sign(fromAccount *Account, keyAuth string, toSign []byte) (signature []byte, err error) {
func (am *AccountManager) Sign(fromAccount *Account, toSign []byte) (signature []byte, err error) {
am.mutex.RLock()
unlockedKey := am.unlockedKeys[string(fromAccount.Address)]
am.mutex.RUnlock()
if unlockedKey.Address == nil {
return nil, ErrLocked
}
signature, err = crypto.Sign(toSign, unlockedKey.PrivateKey)
return signature, err
}
func (am *AccountManager) SignLocked(fromAccount *Account, keyAuth string, toSign []byte) (signature []byte, err error) {
key, err := am.keyStore.GetKey(fromAccount.Address, keyAuth)
if err != nil {
return nil, err
}
am.mutex.RLock()
am.unlockedKeys[string(fromAccount.Address)] = *key
am.mutex.RUnlock()
go unlockLater(am, fromAccount.Address)
signature, err = crypto.Sign(toSign, key.PrivateKey)
return signature, err
}
@ -80,8 +105,6 @@ func (am AccountManager) NewAccount(auth string) (*Account, error) {
return ua, err
}
// set of accounts == set of keys in given key store
// TODO: do we need persistence of accounts as well?
func (am *AccountManager) Accounts() ([]Account, error) {
addresses, err := am.keyStore.GetKeyAddresses()
if err != nil {
@ -97,3 +120,13 @@ func (am *AccountManager) Accounts() ([]Account, error) {
}
return accounts, err
}
func unlockLater(am *AccountManager, addr []byte) {
select {
case <-time.After(time.Millisecond * am.unlockMilliseconds):
}
am.mutex.RLock()
// TODO: how do we know the key is actually gone from memory?
delete(am.unlockedKeys, string(addr))
am.mutex.RUnlock()
}

View File

@ -6,19 +6,68 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/randentropy"
"github.com/ethereum/go-ethereum/ethutil"
"time"
)
func TestAccountManager(t *testing.T) {
ks := crypto.NewKeyStorePlain(ethutil.DefaultDataDir() + "/testaccounts")
am := NewAccountManager(ks)
am := NewAccountManager(ks, 100)
pass := "" // not used but required by API
a1, err := am.NewAccount(pass)
toSign := randentropy.GetEntropyCSPRNG(32)
_, err = am.Sign(a1, pass, toSign)
_, err = am.SignLocked(a1, pass, toSign)
if err != nil {
t.Fatal(err)
}
// Cleanup
time.Sleep(time.Millisecond * 150) // wait for locking
accounts, err := am.Accounts()
if err != nil {
t.Fatal(err)
}
for _, account := range accounts {
err := am.DeleteAccount(account.Address, pass)
if err != nil {
t.Fatal(err)
}
}
}
func TestAccountManagerLocking(t *testing.T) {
ks := crypto.NewKeyStorePassphrase(ethutil.DefaultDataDir() + "/testaccounts")
am := NewAccountManager(ks, 200)
pass := "foo"
a1, err := am.NewAccount(pass)
toSign := randentropy.GetEntropyCSPRNG(32)
// Signing without passphrase fails because account is locked
_, err = am.Sign(a1, toSign)
if err != ErrLocked {
t.Fatal(err)
}
// Signing with passphrase works
_, err = am.SignLocked(a1, pass, toSign)
if err != nil {
t.Fatal(err)
}
// Signing without passphrase works because account is temp unlocked
_, err = am.Sign(a1, toSign)
if err != nil {
t.Fatal(err)
}
// Signing without passphrase fails after automatic locking
time.Sleep(time.Millisecond * time.Duration(250))
_, err = am.Sign(a1, toSign)
if err != ErrLocked {
t.Fatal(err)
}
// Cleanup
accounts, err := am.Accounts()
if err != nil {

View File

@ -27,6 +27,7 @@ import (
"log"
"os"
"path"
"runtime"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethutil"
@ -36,40 +37,42 @@ import (
)
var (
Identifier string
KeyRing string
DiffTool bool
DiffType string
KeyStore string
StartRpc bool
StartWebSockets bool
RpcPort int
WsPort int
OutboundPort string
ShowGenesis bool
AddPeer string
MaxPeer int
GenAddr bool
BootNodes string
NodeKey *ecdsa.PrivateKey
NAT nat.Interface
SecretFile string
ExportDir string
NonInteractive bool
Datadir string
LogFile string
ConfigFile string
DebugFile string
LogLevel int
LogFormat string
Dump bool
DumpHash string
DumpNumber int
VmType int
ImportChain string
SHH bool
Dial bool
PrintVersion bool
Identifier string
KeyRing string
DiffTool bool
DiffType string
KeyStore string
StartRpc bool
StartWebSockets bool
RpcListenAddress string
RpcPort int
WsPort int
OutboundPort string
ShowGenesis bool
AddPeer string
MaxPeer int
GenAddr bool
BootNodes string
NodeKey *ecdsa.PrivateKey
NAT nat.Interface
SecretFile string
ExportDir string
NonInteractive bool
Datadir string
LogFile string
ConfigFile string
DebugFile string
LogLevel int
LogFormat string
Dump bool
DumpHash string
DumpNumber int
VmType int
ImportChain string
SHH bool
Dial bool
PrintVersion bool
MinerThreads int
)
// flags specific to cli client
@ -93,6 +96,7 @@ func Init() {
flag.StringVar(&KeyRing, "keyring", "", "identifier for keyring to use")
flag.StringVar(&KeyStore, "keystore", "db", "system to store keyrings: db|file (db)")
flag.StringVar(&RpcListenAddress, "rpcaddr", "127.0.0.1", "address for json-rpc server to listen on")
flag.IntVar(&RpcPort, "rpcport", 8545, "port to start json-rpc server on")
flag.IntVar(&WsPort, "wsport", 40404, "port to start websocket rpc server on")
flag.BoolVar(&StartRpc, "rpc", false, "start rpc server")
@ -119,6 +123,7 @@ func Init() {
flag.BoolVar(&StartMining, "mine", false, "start dagger mining")
flag.BoolVar(&StartJsConsole, "js", false, "launches javascript console")
flag.BoolVar(&PrintVersion, "version", false, "prints version number")
flag.IntVar(&MinerThreads, "minerthreads", runtime.NumCPU(), "number of miner threads")
// Network stuff
var (
@ -135,6 +140,12 @@ func Init() {
flag.Parse()
// When the javascript console is started log to a file instead
// of stdout
if StartJsConsole {
LogFile = path.Join(Datadir, "ethereum.log")
}
var err error
if NAT, err = nat.Parse(*natstr); err != nil {
log.Fatalf("-nat: %v", err)

View File

@ -37,7 +37,7 @@ import (
const (
ClientIdentifier = "Ethereum(G)"
Version = "0.8.5"
Version = "0.8.6"
)
var clilogger = logger.NewLogger("CLI")
@ -62,20 +62,21 @@ func main() {
utils.InitConfig(VmType, ConfigFile, Datadir, "ETH")
ethereum, err := eth.New(&eth.Config{
Name: p2p.MakeName(ClientIdentifier, Version),
KeyStore: KeyStore,
DataDir: Datadir,
LogFile: LogFile,
LogLevel: LogLevel,
LogFormat: LogFormat,
MaxPeers: MaxPeer,
Port: OutboundPort,
NAT: NAT,
KeyRing: KeyRing,
Shh: true,
Dial: Dial,
BootNodes: BootNodes,
NodeKey: NodeKey,
Name: p2p.MakeName(ClientIdentifier, Version),
KeyStore: KeyStore,
DataDir: Datadir,
LogFile: LogFile,
LogLevel: LogLevel,
LogFormat: LogFormat,
MaxPeers: MaxPeer,
Port: OutboundPort,
NAT: NAT,
KeyRing: KeyRing,
Shh: true,
Dial: Dial,
BootNodes: BootNodes,
NodeKey: NodeKey,
MinerThreads: MinerThreads,
})
if err != nil {
@ -113,10 +114,6 @@ func main() {
return
}
if StartMining {
utils.StartMining(ethereum)
}
if len(ImportChain) > 0 {
start := time.Now()
err := utils.ImportChain(ethereum, ImportChain)
@ -128,7 +125,7 @@ func main() {
}
if StartRpc {
utils.StartRpc(ethereum, RpcPort)
utils.StartRpc(ethereum, RpcListenAddress, RpcPort)
}
if StartWebSockets {
@ -137,6 +134,12 @@ func main() {
utils.StartEthereum(ethereum)
fmt.Printf("Welcome to the FRONTIER\n")
if StartMining {
ethereum.Miner().Start()
}
if StartJsConsole {
InitJsConsole(ethereum)
} else if len(InputFile) > 0 {

View File

@ -60,6 +60,7 @@ func (self *JSRepl) Start() {
if !self.running {
self.running = true
repllogger.Infoln("init JS Console")
reader := bufio.NewReader(self.history)
for {
line, err := reader.ReadString('\n')

View File

@ -62,6 +62,8 @@
web3.setProvider(new web3.providers.HttpSyncProvider('http://localhost:8545'));
eth.defaultBlock = -2
document.querySelector("#number").innerHTML = eth.number;
document.querySelector("#coinbase").innerHTML = eth.coinbase
document.querySelector("#peer_count").innerHTML = eth.peerCount;
@ -72,8 +74,9 @@
document.querySelector("#mining").innerHTML = eth.mining;
document.querySelector("#listening").innerHTML = eth.listening;
eth.watch('chain').changed(function() {
document.querySelector("#number").innerHTML = eth.number;
});
document.querySelector("#number").innerHTML = eth.number;
});
</script>

File diff suppressed because it is too large Load Diff

View File

@ -964,7 +964,7 @@ ApplicationWindow {
anchors.top: parent.top
anchors.topMargin: 30
font.pointSize: 12
text: "<h2>Mist (0.8.5)</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Viktor Trón<br>Felix Lange<br>Taylor Gerring<br>Daniel Nagy<br>Gustav Simonsson<br><h3>UX/UI</h3>Alex van de Sande<br>Fabian Vogelsteller"
text: "<h2>Mist (0.8.6)</h2><br><h3>Development</h3>Jeffrey Wilcke<br>Viktor Trón<br>Felix Lange<br>Taylor Gerring<br>Daniel Nagy<br>Gustav Simonsson<br><h3>UX/UI</h3>Alex van de Sande<br>Fabian Vogelsteller"
}
}

View File

@ -27,10 +27,8 @@ import (
"log"
"os"
"path"
"path/filepath"
"runtime"
"bitbucket.org/kardianos/osext"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/logger"
@ -39,62 +37,36 @@ import (
)
var (
Identifier string
KeyRing string
KeyStore string
StartRpc bool
StartWebSockets bool
RpcPort int
WsPort int
OutboundPort string
ShowGenesis bool
AddPeer string
MaxPeer int
GenAddr bool
BootNodes string
NodeKey *ecdsa.PrivateKey
NAT nat.Interface
SecretFile string
ExportDir string
NonInteractive bool
Datadir string
LogFile string
ConfigFile string
DebugFile string
LogLevel int
VmType int
MinerThreads int
Identifier string
KeyRing string
KeyStore string
StartRpc bool
StartWebSockets bool
RpcListenAddress string
RpcPort int
WsPort int
OutboundPort string
ShowGenesis bool
AddPeer string
MaxPeer int
GenAddr bool
BootNodes string
NodeKey *ecdsa.PrivateKey
NAT nat.Interface
SecretFile string
ExportDir string
NonInteractive bool
Datadir string
LogFile string
ConfigFile string
DebugFile string
LogLevel int
VmType int
MinerThreads int
)
// flags specific to gui client
var AssetPath string
//TODO: If we re-use the one defined in cmd.go the binary osx image crashes. If somebody finds out why we can dry this up.
func defaultAssetPath() string {
var assetPath string
// If the current working directory is the go-ethereum dir
// assume a debug build and use the source directory as
// asset directory.
pwd, _ := os.Getwd()
if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist") {
assetPath = path.Join(pwd, "assets")
} else {
switch runtime.GOOS {
case "darwin":
// Get Binary Directory
exedir, _ := osext.ExecutableFolder()
assetPath = filepath.Join(exedir, "../Resources")
case "linux":
assetPath = "/usr/share/mist"
case "windows":
assetPath = "./assets"
default:
assetPath = "."
}
}
return assetPath
}
var defaultConfigFile = path.Join(ethutil.DefaultDataDir(), "conf.ini")
func Init() {
@ -108,6 +80,7 @@ func Init() {
flag.StringVar(&Identifier, "id", "", "Custom client identifier")
flag.StringVar(&KeyRing, "keyring", "", "identifier for keyring to use")
flag.StringVar(&KeyStore, "keystore", "db", "system to store keyrings: db|file (db)")
flag.StringVar(&RpcListenAddress, "rpcaddr", "127.0.0.1", "address for json-rpc server to listen on")
flag.IntVar(&RpcPort, "rpcport", 8545, "port to start json-rpc server on")
flag.IntVar(&WsPort, "wsport", 40404, "port to start websocket rpc server on")
flag.BoolVar(&StartRpc, "rpc", true, "start rpc server")
@ -122,7 +95,7 @@ func Init() {
flag.StringVar(&DebugFile, "debug", "", "debug file (no debugging if not set)")
flag.IntVar(&LogLevel, "loglevel", int(logger.InfoLevel), "loglevel: 0-5: silent,error,warn,info,debug,debug detail)")
flag.StringVar(&AssetPath, "asset_path", defaultAssetPath(), "absolute path to GUI assets directory")
flag.StringVar(&AssetPath, "asset_path", ethutil.DefaultAssetPath(), "absolute path to GUI assets directory")
// Network stuff
var (

View File

@ -36,7 +36,7 @@ import (
const (
ClientIdentifier = "Mist"
Version = "0.8.5"
Version = "0.8.6"
)
var ethereum *eth.Ethereum
@ -73,7 +73,7 @@ func run() error {
utils.KeyTasks(ethereum.KeyManager(), KeyRing, GenAddr, SecretFile, ExportDir, NonInteractive)
if StartRpc {
utils.StartRpc(ethereum, RpcPort)
utils.StartRpc(ethereum, RpcListenAddress, RpcPort)
}
if StartWebSockets {

View File

@ -25,12 +25,8 @@ import (
"fmt"
"os"
"os/signal"
"path"
"path/filepath"
"regexp"
"runtime"
"bitbucket.org/kardianos/osext"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
@ -132,31 +128,6 @@ func StartEthereum(ethereum *eth.Ethereum) {
})
}
func DefaultAssetPath() string {
var assetPath string
// If the current working directory is the go-ethereum dir
// assume a debug build and use the source directory as
// asset directory.
pwd, _ := os.Getwd()
if pwd == path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist") {
assetPath = path.Join(pwd, "assets")
} else {
switch runtime.GOOS {
case "darwin":
// Get Binary Directory
exedir, _ := osext.ExecutableFolder()
assetPath = filepath.Join(exedir, "../Resources")
case "linux":
assetPath = "/usr/share/mist"
case "windows":
assetPath = "./assets"
default:
assetPath = "."
}
}
return assetPath
}
func KeyTasks(keyManager *crypto.KeyManager, KeyRing string, GenAddr bool, SecretFile string, ExportDir string, NonInteractive bool) {
var err error
@ -189,9 +160,9 @@ func KeyTasks(keyManager *crypto.KeyManager, KeyRing string, GenAddr bool, Secre
clilogger.Infof("Main address %x\n", keyManager.Address())
}
func StartRpc(ethereum *eth.Ethereum, RpcPort int) {
func StartRpc(ethereum *eth.Ethereum, RpcListenAddress string, RpcPort int) {
var err error
ethereum.RpcServer, err = rpchttp.NewRpcHttpServer(xeth.New(ethereum), RpcPort)
ethereum.RpcServer, err = rpchttp.NewRpcHttpServer(xeth.New(ethereum), RpcListenAddress, RpcPort)
if err != nil {
clilogger.Errorf("Could not start RPC interface (port %v): %v", RpcPort, err)
} else {

View File

@ -48,9 +48,8 @@ type BlockProcessor struct {
func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainManager, eventMux *event.TypeMux) *BlockProcessor {
sm := &BlockProcessor{
db: db,
mem: make(map[string]*big.Int),
//Pow: &ethash.Ethash{},
db: db,
mem: make(map[string]*big.Int),
Pow: ezp.New(),
bc: chainManager,
eventMux: eventMux,
@ -62,7 +61,7 @@ func NewBlockProcessor(db ethutil.Database, txpool *TxPool, chainManager *ChainM
func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block *types.Block, transientProcess bool) (receipts types.Receipts, err error) {
coinbase := statedb.GetOrNewStateObject(block.Header().Coinbase)
coinbase.SetGasPool(CalcGasLimit(parent, block))
coinbase.SetGasPool(block.Header().GasLimit)
// Process the transactions on to parent state
receipts, _, _, _, err = sm.ApplyTransactions(coinbase, statedb, block, block.Transactions(), transientProcess)
@ -100,7 +99,8 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated
// Notify all subscribers
if !transientProcess {
go self.eventMux.Post(TxPostEvent{tx})
go self.eventMux.Post(statedb.Logs())
logs := statedb.Logs()
go self.eventMux.Post(logs)
}
return receipt, txGas, err
@ -247,6 +247,11 @@ func (sm *BlockProcessor) ValidateBlock(block, parent *types.Block) error {
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Header().Difficulty, expd)
}
expl := CalcGasLimit(parent, block)
if expl.Cmp(block.Header().GasLimit) != 0 {
return fmt.Errorf("GasLimit check failed for block %v, %v", block.Header().GasLimit, expl)
}
if block.Time() < parent.Time() {
return ValidationError("Block timestamp not after prev block (%v - %v)", block.Header().Time, parent.Header().Time)
}

View File

@ -51,8 +51,6 @@ func GenesisBlock(db ethutil.Database) *types.Block {
statedb.Sync()
genesis.Header().Root = statedb.Root()
fmt.Printf("+++ genesis +++\nRoot: %x\nHash: %x\n", genesis.Header().Root, genesis.Hash())
return genesis
}

View File

@ -126,7 +126,7 @@ func (self *StateTransition) BuyGas() error {
self.AddGas(self.msg.Gas())
self.initialGas.Set(self.msg.Gas())
sender.SubAmount(MessageGasValue(self.msg))
sender.SubBalance(MessageGasValue(self.msg))
return nil
}
@ -251,7 +251,7 @@ func (self *StateTransition) RefundGas() {
coinbase, sender := self.Coinbase(), self.From()
// Return remaining gas
remaining := new(big.Int).Mul(self.gas, self.msg.GasPrice())
sender.AddAmount(remaining)
sender.AddBalance(remaining)
uhalf := new(big.Int).Div(self.GasUsed(), ethutil.Big2)
for addr, ref := range self.state.Refunds() {

View File

@ -148,7 +148,8 @@ func New(config *Config) (*Ethereum, error) {
d, _ := db.Get([]byte("ProtocolVersion"))
protov := ethutil.NewValue(d).Uint()
if protov != ProtocolVersion && protov != 0 {
return nil, fmt.Errorf("Database version mismatch. Protocol(%d / %d). `rm -rf %s`", protov, ProtocolVersion, ethutil.Config.ExecPath+"/database")
path := path.Join(config.DataDir, "database")
return nil, fmt.Errorf("Database version mismatch. Protocol(%d / %d). `rm -rf %s`", protov, ProtocolVersion, path)
}
// Create new keymanager

View File

@ -3,12 +3,50 @@ package ethutil
import (
"fmt"
"math/big"
"os"
"os/user"
"path"
"path/filepath"
"runtime"
"time"
"github.com/kardianos/osext"
)
func DefaultAssetPath() string {
var assetPath string
pwd, _ := os.Getwd()
srcdir := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist")
// If the current working directory is the go-ethereum dir
// assume a debug build and use the source directory as
// asset directory.
if pwd == srcdir {
assetPath = path.Join(pwd, "assets")
} else {
switch runtime.GOOS {
case "darwin":
// Get Binary Directory
exedir, _ := osext.ExecutableFolder()
assetPath = filepath.Join(exedir, "../Resources")
case "linux":
assetPath = "/usr/share/mist"
case "windows":
assetPath = "./assets"
default:
assetPath = "."
}
}
// Check if the assetPath exists. If not, try the source directory
// This happens when binary is run from outside cmd/mist directory
if _, err := os.Stat(assetPath); os.IsNotExist(err) {
assetPath = path.Join(srcdir, "assets")
}
return assetPath
}
func DefaultDataDir() string {
usr, _ := user.Current()
if runtime.GOOS == "darwin" {

View File

@ -24,7 +24,7 @@ var jsrelogger = logger.NewLogger("JSRE")
type JSRE struct {
ethereum *eth.Ethereum
Vm *otto.Otto
pipe *xeth.XEth
xeth *xeth.XEth
events event.Subscription
@ -67,7 +67,7 @@ func NewJSRE(ethereum *eth.Ethereum) *JSRE {
// We have to make sure that, whoever calls this, calls "Stop"
go re.mainLoop()
re.Bind("eth", &JSEthereum{re.pipe, re.Vm, ethereum})
re.Bind("eth", &JSEthereum{re.xeth, re.Vm, ethereum})
re.initStdFuncs()
@ -113,12 +113,10 @@ func (self *JSRE) mainLoop() {
func (self *JSRE) initStdFuncs() {
t, _ := self.Vm.Get("eth")
eth := t.Object()
eth.Set("watch", self.watch)
eth.Set("addPeer", self.addPeer)
eth.Set("connect", self.connect)
eth.Set("require", self.require)
eth.Set("stopMining", self.stopMining)
eth.Set("startMining", self.startMining)
eth.Set("execBlock", self.execBlock)
eth.Set("dump", self.dump)
eth.Set("export", self.export)
}
@ -152,7 +150,8 @@ func (self *JSRE) dump(call otto.FunctionCall) otto.Value {
}
statedb := state.New(block.Root(), self.ethereum.Db())
v, _ := self.Vm.ToValue(statedb.Dump())
v, _ := self.Vm.ToValue(statedb.RawDump())
return v
}
@ -167,36 +166,7 @@ func (self *JSRE) startMining(call otto.FunctionCall) otto.Value {
return v
}
// eth.watch
func (self *JSRE) watch(call otto.FunctionCall) otto.Value {
addr, _ := call.Argument(0).ToString()
var storageAddr string
var cb otto.Value
var storageCallback bool
if len(call.ArgumentList) > 2 {
storageCallback = true
storageAddr, _ = call.Argument(1).ToString()
cb = call.Argument(2)
} else {
cb = call.Argument(1)
}
if storageCallback {
self.objectCb[addr+storageAddr] = append(self.objectCb[addr+storageAddr], cb)
// event := "storage:" + string(ethutil.Hex2Bytes(addr)) + ":" + string(ethutil.Hex2Bytes(storageAddr))
// self.ethereum.EventMux().Subscribe(event, self.changeChan)
} else {
self.objectCb[addr] = append(self.objectCb[addr], cb)
// event := "object:" + string(ethutil.Hex2Bytes(addr))
// self.ethereum.EventMux().Subscribe(event, self.changeChan)
}
return otto.UndefinedValue()
}
func (self *JSRE) addPeer(call otto.FunctionCall) otto.Value {
func (self *JSRE) connect(call otto.FunctionCall) otto.Value {
nodeURL, err := call.Argument(0).ToString()
if err != nil {
return otto.FalseValue()
@ -222,22 +192,12 @@ func (self *JSRE) require(call otto.FunctionCall) otto.Value {
return t
}
func (self *JSRE) execBlock(call otto.FunctionCall) otto.Value {
hash, err := call.Argument(0).ToString()
if err != nil {
return otto.UndefinedValue()
}
err = utils.BlockDo(self.ethereum, ethutil.Hex2Bytes(hash))
if err != nil {
fmt.Println(err)
func (self *JSRE) export(call otto.FunctionCall) otto.Value {
if len(call.ArgumentList) == 0 {
fmt.Println("err: require file name")
return otto.FalseValue()
}
return otto.TrueValue()
}
func (self *JSRE) export(call otto.FunctionCall) otto.Value {
fn, err := call.Argument(0).ToString()
if err != nil {
fmt.Println(err)

View File

@ -16,7 +16,7 @@ function pp(object) {
str += " ]";
} else if(typeof(object) === "object") {
str += "{ ";
var last = Object.keys(object).sort().pop()
var last = Object.keys(object).pop()
for(var k in object) {
str += k + ": " + pp(object[k]);

View File

@ -52,10 +52,5 @@ func (self *Miner) Stop() {
}
func (self *Miner) HashRate() int64 {
var tot int64
for _, agent := range self.worker.agents {
tot += agent.Pow().GetHashrate()
}
return tot
return self.worker.HashRate()
}

View File

@ -5,6 +5,7 @@ import (
"math/big"
"sort"
"sync"
"time"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
@ -111,6 +112,8 @@ func (self *worker) register(agent Agent) {
func (self *worker) update() {
events := self.mux.Subscribe(core.ChainEvent{}, core.NewMinedBlockEvent{})
timer := time.NewTicker(2 * time.Second)
out:
for {
select {
@ -129,6 +132,8 @@ out:
agent.Stop()
}
break out
case <-timer.C:
minerlogger.Debugln("Hash rate:", self.HashRate(), "Khash")
}
}
@ -197,7 +202,7 @@ gasLimit:
}
self.eth.TxPool().RemoveSet(remove)
self.current.coinbase.AddAmount(core.BlockReward)
self.current.coinbase.AddBalance(core.BlockReward)
self.current.state.Update(ethutil.Big0)
self.push()
@ -225,7 +230,7 @@ func (self *worker) commitUncle(uncle *types.Header) error {
}
uncleAccount := self.current.state.GetAccount(uncle.Coinbase)
uncleAccount.AddAmount(uncleReward)
uncleAccount.AddBalance(uncleReward)
self.current.coinbase.AddBalance(uncleReward)
@ -244,3 +249,12 @@ func (self *worker) commitTransaction(tx *types.Transaction) error {
return nil
}
func (self *worker) HashRate() int64 {
var tot int64
for _, agent := range self.agents {
tot += agent.Pow().GetHashrate()
}
return tot
}

View File

@ -9,6 +9,7 @@ For each request type, define the following:
package rpc
import (
"fmt"
"math/big"
"strings"
"sync"
@ -19,8 +20,10 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/ethutil"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/event/filter"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/ui"
"github.com/ethereum/go-ethereum/xeth"
)
@ -31,7 +34,10 @@ var (
)
type EthereumApi struct {
xeth *xeth.XEth
eth *xeth.XEth
xethMu sync.RWMutex
mux *event.TypeMux
quit chan struct{}
filterManager *filter.FilterManager
@ -45,17 +51,21 @@ type EthereumApi struct {
register map[string][]*NewTxArgs
db ethutil.Database
defaultBlockAge int64
}
func NewEthereumApi(eth *xeth.XEth) *EthereumApi {
db, _ := ethdb.NewLDBDatabase("dapps")
api := &EthereumApi{
xeth: eth,
quit: make(chan struct{}),
filterManager: filter.NewFilterManager(eth.Backend().EventMux()),
logs: make(map[int]*logFilter),
messages: make(map[int]*whisperFilter),
db: db,
eth: eth,
mux: eth.Backend().EventMux(),
quit: make(chan struct{}),
filterManager: filter.NewFilterManager(eth.Backend().EventMux()),
logs: make(map[int]*logFilter),
messages: make(map[int]*whisperFilter),
db: db,
defaultBlockAge: -1,
}
go api.filterManager.Start()
go api.start()
@ -63,11 +73,36 @@ func NewEthereumApi(eth *xeth.XEth) *EthereumApi {
return api
}
func (self *EthereumApi) setStateByBlockNumber(num int64) {
chain := self.xeth().Backend().ChainManager()
var block *types.Block
if self.defaultBlockAge < 0 {
num = chain.CurrentBlock().Number().Int64() + num + 1
}
block = chain.GetBlockByNumber(uint64(num))
if block != nil {
self.useState(state.New(block.Root(), self.xeth().Backend().Db()))
} else {
self.useState(chain.State())
}
}
func (self *EthereumApi) start() {
timer := time.NewTicker(filterTickerTime)
events := self.mux.Subscribe(core.ChainEvent{})
done:
for {
select {
case ev := <-events.Chan():
switch ev.(type) {
case core.ChainEvent:
if self.defaultBlockAge < 0 {
self.setStateByBlockNumber(self.defaultBlockAge)
}
}
case <-timer.C:
self.logMut.Lock()
self.messagesMut.Lock()
@ -80,7 +115,7 @@ done:
for id, filter := range self.messages {
if time.Since(filter.timeout) > 20*time.Second {
self.xeth.Whisper().Unwatch(id)
self.xeth().Whisper().Unwatch(id)
delete(self.messages, id)
}
}
@ -128,7 +163,7 @@ func (self *EthereumApi) WatchTx(args string, reply *interface{}) error {
func (self *EthereumApi) NewFilter(args *FilterOptions, reply *interface{}) error {
var id int
filter := core.NewFilter(self.xeth.Backend())
filter := core.NewFilter(self.xeth().Backend())
filter.SetOptions(toFilterOptions(args))
filter.LogsCallback = func(logs state.Logs) {
self.logMut.Lock()
@ -153,7 +188,7 @@ func (self *EthereumApi) UninstallFilter(id int, reply *interface{}) error {
func (self *EthereumApi) NewFilterString(args string, reply *interface{}) error {
var id int
filter := core.NewFilter(self.xeth.Backend())
filter := core.NewFilter(self.xeth().Backend())
callback := func(block *types.Block) {
self.logMut.Lock()
@ -198,7 +233,7 @@ func (self *EthereumApi) Logs(id int, reply *interface{}) error {
}
func (self *EthereumApi) AllLogs(args *FilterOptions, reply *interface{}) error {
filter := core.NewFilter(self.xeth.Backend())
filter := core.NewFilter(self.xeth().Backend())
filter.SetOptions(toFilterOptions(args))
*reply = toLogs(filter.Find())
@ -209,9 +244,9 @@ func (self *EthereumApi) AllLogs(args *FilterOptions, reply *interface{}) error
func (p *EthereumApi) GetBlock(args *GetBlockArgs, reply *interface{}) error {
// This seems a bit precarious Maybe worth splitting to discrete functions
if len(args.Hash) > 0 {
*reply = p.xeth.BlockByHash(args.Hash)
*reply = p.xeth().BlockByHash(args.Hash)
} else {
*reply = p.xeth.BlockByNumber(args.BlockNumber)
*reply = p.xeth().BlockByNumber(args.BlockNumber)
}
return nil
}
@ -226,18 +261,35 @@ func (p *EthereumApi) Transact(args *NewTxArgs, reply *interface{}) error {
}
// TODO if no_private_key then
if _, exists := p.register[args.From]; exists {
p.register[args.From] = append(p.register[args.From], args)
} else {
result, _ := p.xeth.Transact( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data)
*reply = result
}
//if _, exists := p.register[args.From]; exists {
// p.register[args.From] = append(p.register[args.From], args)
//} else {
/*
account := accounts.Get(fromHex(args.From))
if account != nil {
if account.Unlocked() {
if !unlockAccount(account) {
return
}
}
result, _ := account.Transact(fromHex(args.To), fromHex(args.Value), fromHex(args.Gas), fromHex(args.GasPrice), fromHex(args.Data))
if len(result) > 0 {
*reply = toHex(result)
}
} else if _, exists := p.register[args.From]; exists {
p.register[ags.From] = append(p.register[args.From], args)
}
*/
result, _ := p.xeth().Transact( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data)
*reply = result
//}
return nil
}
func (p *EthereumApi) Call(args *NewTxArgs, reply *interface{}) error {
result, err := p.xeth.Call( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data)
result, err := p.xeth().Call( /* TODO specify account */ args.To, args.Value, args.Gas, args.GasPrice, args.Data)
if err != nil {
return err
}
@ -251,7 +303,7 @@ func (p *EthereumApi) PushTx(args *PushTxArgs, reply *interface{}) error {
if err != nil {
return err
}
result, _ := p.xeth.PushTx(args.Tx)
result, _ := p.xeth().PushTx(args.Tx)
*reply = result
return nil
}
@ -262,7 +314,7 @@ func (p *EthereumApi) GetStateAt(args *GetStateArgs, reply *interface{}) error {
return err
}
state := p.xeth.State().SafeGet(args.Address)
state := p.xeth().State().SafeGet(args.Address)
value := state.StorageString(args.Key)
var hx string
@ -284,42 +336,55 @@ func (p *EthereumApi) GetStorageAt(args *GetStorageArgs, reply *interface{}) err
return err
}
*reply = p.xeth.State().SafeGet(args.Address).Storage()
*reply = p.xeth().State().SafeGet(args.Address).Storage()
return nil
}
func (p *EthereumApi) GetPeerCount(reply *interface{}) error {
*reply = p.xeth.PeerCount()
*reply = p.xeth().PeerCount()
return nil
}
func (p *EthereumApi) GetIsListening(reply *interface{}) error {
*reply = p.xeth.IsListening()
*reply = p.xeth().IsListening()
return nil
}
func (p *EthereumApi) GetCoinbase(reply *interface{}) error {
*reply = p.xeth.Coinbase()
*reply = p.xeth().Coinbase()
return nil
}
func (p *EthereumApi) Accounts(reply *interface{}) error {
*reply = p.xeth.Accounts()
*reply = p.xeth().Accounts()
return nil
}
func (p *EthereumApi) GetIsMining(reply *interface{}) error {
*reply = p.xeth.IsMining()
*reply = p.xeth().IsMining()
return nil
}
func (p *EthereumApi) SetMining(shouldmine bool, reply *interface{}) error {
*reply = p.xeth.SetMining(shouldmine)
*reply = p.xeth().SetMining(shouldmine)
return nil
}
func (p *EthereumApi) GetDefaultBlockAge(reply *interface{}) error {
*reply = p.defaultBlockAge
return nil
}
func (p *EthereumApi) SetDefaultBlockAge(defaultBlockAge int64, reply *interface{}) error {
p.defaultBlockAge = defaultBlockAge
p.setStateByBlockNumber(p.defaultBlockAge)
*reply = true
return nil
}
func (p *EthereumApi) BlockNumber(reply *interface{}) error {
*reply = p.xeth.Backend().ChainManager().CurrentBlock().Number()
*reply = p.xeth().Backend().ChainManager().CurrentBlock().Number()
return nil
}
@ -328,7 +393,7 @@ func (p *EthereumApi) GetTxCountAt(args *GetTxCountArgs, reply *interface{}) err
if err != nil {
return err
}
*reply = p.xeth.TxCountAt(args.Address)
*reply = p.xeth().TxCountAt(args.Address)
return nil
}
@ -337,7 +402,7 @@ func (p *EthereumApi) GetBalanceAt(args *GetBalanceArgs, reply *interface{}) err
if err != nil {
return err
}
state := p.xeth.State().SafeGet(args.Address)
state := p.xeth().State().SafeGet(args.Address)
*reply = toHex(state.Balance().Bytes())
return nil
}
@ -347,7 +412,7 @@ func (p *EthereumApi) GetCodeAt(args *GetCodeAtArgs, reply *interface{}) error {
if err != nil {
return err
}
*reply = p.xeth.CodeAt(args.Address)
*reply = p.xeth().CodeAt(args.Address)
return nil
}
@ -394,7 +459,7 @@ func (p *EthereumApi) DbGet(args *DbArgs, reply *interface{}) error {
}
func (p *EthereumApi) NewWhisperIdentity(reply *interface{}) error {
*reply = p.xeth.Whisper().NewIdentity()
*reply = p.xeth().Whisper().NewIdentity()
return nil
}
@ -405,7 +470,7 @@ func (p *EthereumApi) NewWhisperFilter(args *xeth.Options, reply *interface{}) e
defer p.messagesMut.Unlock()
p.messages[id].add(msg) // = append(p.messages[id], msg)
}
id = p.xeth.Whisper().Watch(args)
id = p.xeth().Whisper().Watch(args)
p.messages[id] = &whisperFilter{timeout: time.Now()}
*reply = id
return nil
@ -423,7 +488,7 @@ func (self *EthereumApi) MessagesChanged(id int, reply *interface{}) error {
}
func (p *EthereumApi) WhisperPost(args *WhisperMessageArgs, reply *interface{}) error {
err := p.xeth.Whisper().Post(args.Payload, args.To, args.From, args.Topic, args.Priority, args.Ttl)
err := p.xeth().Whisper().Post(args.Payload, args.To, args.From, args.Topic, args.Priority, args.Ttl)
if err != nil {
return err
}
@ -433,12 +498,12 @@ func (p *EthereumApi) WhisperPost(args *WhisperMessageArgs, reply *interface{})
}
func (p *EthereumApi) HasWhisperIdentity(args string, reply *interface{}) error {
*reply = p.xeth.Whisper().HasIdentity(args)
*reply = p.xeth().Whisper().HasIdentity(args)
return nil
}
func (p *EthereumApi) WhisperMessages(id int, reply *interface{}) error {
*reply = p.xeth.Whisper().Messages(id)
*reply = p.xeth().Whisper().Messages(id)
return nil
}
@ -458,6 +523,14 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
return err
}
return p.SetMining(args, reply)
case "eth_defaultBlock":
return p.GetDefaultBlockAge(reply)
case "eth_setDefaultBlock":
args, err := req.ToIntArgs()
if err != nil {
return err
}
return p.SetDefaultBlockAge(int64(args), reply)
case "eth_peerCount":
return p.GetPeerCount(reply)
case "eth_number":
@ -634,3 +707,28 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
rpclogger.DebugDetailf("Reply: %T %s", reply, reply)
return nil
}
func (self *EthereumApi) xeth() *xeth.XEth {
self.xethMu.RLock()
defer self.xethMu.RUnlock()
return self.eth
}
func (self *EthereumApi) useState(statedb *state.StateDB) {
self.xethMu.Lock()
defer self.xethMu.Unlock()
self.eth = self.eth.UseState(statedb)
}
func t(f ui.Frontend) {
// Call the password dialog
ret, err := f.Call("PasswordDialog")
if err != nil {
fmt.Println(err)
}
// Get the first argument
t, _ := ret.Get(0)
fmt.Println("return:", t)
}

View File

@ -29,8 +29,8 @@ import (
var rpchttplogger = logger.NewLogger("RPC-HTTP")
var JSON rpc.JsonWrapper
func NewRpcHttpServer(pipe *xeth.XEth, port int) (*RpcHttpServer, error) {
sport := fmt.Sprintf("127.0.0.1:%d", port)
func NewRpcHttpServer(pipe *xeth.XEth, address string, port int) (*RpcHttpServer, error) {
sport := fmt.Sprintf("%s:%d", address, port)
l, err := net.Listen("tcp", sport)
if err != nil {
return nil, err
@ -41,6 +41,7 @@ func NewRpcHttpServer(pipe *xeth.XEth, port int) (*RpcHttpServer, error) {
quit: make(chan bool),
pipe: pipe,
port: port,
addr: address,
}, nil
}
@ -49,6 +50,7 @@ type RpcHttpServer struct {
listener net.Listener
pipe *xeth.XEth
port int
addr string
}
func (s *RpcHttpServer) exitHandler() {
@ -69,7 +71,7 @@ func (s *RpcHttpServer) Stop() {
}
func (s *RpcHttpServer) Start() {
rpchttplogger.Infof("Starting RPC-HTTP server on port %d", s.port)
rpchttplogger.Infof("Starting RPC-HTTP server on %s:%d", s.addr, s.port)
go s.exitHandler()
api := rpc.NewEthereumApi(s.pipe)

View File

@ -210,6 +210,19 @@ func (req *RpcRequest) ToBoolArgs() (bool, error) {
return args, nil
}
func (req *RpcRequest) ToIntArgs() (int, error) {
if len(req.Params) < 1 {
return 0, errArguments
}
var args int
if err := json.Unmarshal(req.Params[0], &args); err != nil {
return 0, errArguments
}
return args, nil
}
func (req *RpcRequest) ToCompileArgs() (string, error) {
if len(req.Params) < 1 {
return "", errArguments

View File

@ -20,7 +20,7 @@ type World struct {
Accounts map[string]Account `json:"accounts"`
}
func (self *StateDB) Dump() []byte {
func (self *StateDB) RawDump() World {
world := World{
Root: ethutil.Bytes2Hex(self.trie.Root()),
Accounts: make(map[string]Account),
@ -35,12 +35,15 @@ func (self *StateDB) Dump() []byte {
storageIt := stateObject.State.trie.Iterator()
for storageIt.Next() {
account.Storage[ethutil.Bytes2Hex(it.Key)] = ethutil.Bytes2Hex(it.Value)
account.Storage[ethutil.Bytes2Hex(storageIt.Key)] = ethutil.Bytes2Hex(storageIt.Value)
}
world.Accounts[ethutil.Bytes2Hex(it.Key)] = account
}
return world
}
json, err := json.MarshalIndent(world, "", " ")
func (self *StateDB) Dump() []byte {
json, err := json.MarshalIndent(self.RawDump(), "", " ")
if err != nil {
fmt.Println("dump err", err)
}

View File

@ -19,6 +19,14 @@ func (self Code) String() string {
type Storage map[string]*ethutil.Value
func (self Storage) String() (str string) {
for key, value := range self {
str += fmt.Sprintf("%X : %X\n", key, value.Bytes())
}
return
}
func (self Storage) Copy() Storage {
cpy := make(Storage)
for key, value := range self {
@ -119,10 +127,9 @@ func (self *StateObject) GetStorage(key *big.Int) *ethutil.Value {
}
func (self *StateObject) SetStorage(key *big.Int, value *ethutil.Value) {
self.SetState(key.Bytes(), value)
self.dirty = true
}
func (self *StateObject) Storage() map[string]*ethutil.Value {
func (self *StateObject) Storage() Storage {
return self.storage
}
@ -172,20 +179,22 @@ func (c *StateObject) AddBalance(amount *big.Int) {
statelogger.Debugf("%x: #%d %v (+ %v)\n", c.Address(), c.nonce, c.balance, amount)
}
func (c *StateObject) AddAmount(amount *big.Int) { c.AddBalance(amount) }
func (c *StateObject) SubBalance(amount *big.Int) {
c.SetBalance(new(big.Int).Sub(c.balance, amount))
statelogger.Debugf("%x: #%d %v (- %v)\n", c.Address(), c.nonce, c.balance, amount)
}
func (c *StateObject) SubAmount(amount *big.Int) { c.SubBalance(amount) }
func (c *StateObject) SetBalance(amount *big.Int) {
c.balance = amount
c.dirty = true
}
func (c *StateObject) St() Storage {
return c.storage
}
//
// Gas setters and getters
//
@ -198,7 +207,7 @@ func (c *StateObject) ConvertGas(gas, price *big.Int) error {
return fmt.Errorf("insufficient amount: %v, %v", c.balance, total)
}
c.SubAmount(total)
c.SubBalance(total)
c.dirty = true
@ -221,7 +230,7 @@ func (self *StateObject) BuyGas(gas, price *big.Int) error {
rGas := new(big.Int).Set(gas)
rGas.Mul(rGas, price)
self.AddAmount(rGas)
self.AddBalance(rGas)
self.dirty = true

18
ui/frontend.go Normal file
View File

@ -0,0 +1,18 @@
package ui
// ReturnInterface is returned by the Intercom interface when a method is called
type ReturnInterface interface {
Get(i int) (interface{}, error)
Size() int
}
// Frontend is the basic interface for calling arbitrary methods on something that
// implements a front end (GUI, CLI, etc)
type Frontend interface {
// Checks whether a specific method is implemented
Supports(method string) bool
// Call calls the given method on interface it implements. This will return
// an error with errNotImplemented if the method hasn't been implemented
// and will return a ReturnInterface if it does.
Call(method string) (ReturnInterface, error)
}

View File

@ -16,6 +16,8 @@ type Vm struct {
logStr string
err error
// For logging
debug bool
Dbg Debugger
@ -32,7 +34,7 @@ func New(env Environment) *Vm {
lt = LogTyDiff
}
return &Vm{env: env, logTy: lt, Recoverable: true}
return &Vm{debug: false, env: env, logTy: lt, Recoverable: true}
}
func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.Int, callData []byte) (ret []byte, err error) {
@ -664,6 +666,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
}
addr = ref.Address()
fmt.Printf("CREATE %X\n", addr)
stack.Push(ethutil.BigD(addr))
}
@ -727,7 +730,7 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
self.Printf(" => (%x) %v", receiver.Address()[:4], balance)
receiver.AddAmount(balance)
receiver.AddBalance(balance)
statedb.Delete(context.Address())
fallthrough
@ -828,7 +831,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
// 0 => non 0
mult = ethutil.Big3
} else if len(val) > 0 && len(y.Bytes()) == 0 {
statedb.Refund(caller.Address(), GasSStoreRefund)
statedb.Refund(self.env.Origin(), GasSStoreRefund)
mult = ethutil.Big0
} else {
@ -937,17 +940,21 @@ func (self *Vm) RunPrecompiled(p *PrecompiledAccount, callData []byte, context *
}
func (self *Vm) Printf(format string, v ...interface{}) VirtualMachine {
if self.logTy == LogTyPretty {
self.logStr += fmt.Sprintf(format, v...)
if self.debug {
if self.logTy == LogTyPretty {
self.logStr += fmt.Sprintf(format, v...)
}
}
return self
}
func (self *Vm) Endl() VirtualMachine {
if self.logTy == LogTyPretty {
vmlogger.Debugln(self.logStr)
self.logStr = ""
if self.debug {
if self.logTy == LogTyPretty {
vmlogger.Debugln(self.logStr)
self.logStr = ""
}
}
return self

View File

@ -3,19 +3,20 @@ package xeth
import "github.com/ethereum/go-ethereum/state"
type State struct {
xeth *XEth
xeth *XEth
state *state.StateDB
}
func NewState(xeth *XEth) *State {
return &State{xeth}
func NewState(xeth *XEth, statedb *state.StateDB) *State {
return &State{xeth, statedb}
}
func (self *State) State() *state.StateDB {
return self.xeth.chainManager.TransState()
return self.state
}
func (self *State) Get(addr string) *Object {
return &Object{self.State().GetStateObject(fromHex(addr))}
return &Object{self.state.GetStateObject(fromHex(addr))}
}
func (self *State) SafeGet(addr string) *Object {
@ -23,7 +24,7 @@ func (self *State) SafeGet(addr string) *Object {
}
func (self *State) safeGet(addr string) *state.StateObject {
object := self.State().GetStateObject(fromHex(addr))
object := self.state.GetStateObject(fromHex(addr))
if object == nil {
object = state.NewStateObject(fromHex(addr), self.xeth.eth.Db())
}

View File

@ -17,6 +17,7 @@ import (
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/whisper"
)
@ -54,13 +55,26 @@ func New(eth Backend) *XEth {
whisper: NewWhisper(eth.Whisper()),
miner: eth.Miner(),
}
xeth.state = NewState(xeth)
xeth.state = NewState(xeth, xeth.chainManager.TransState())
return xeth
}
func (self *XEth) Backend() Backend { return self.eth }
func (self *XEth) State() *State { return self.state }
func (self *XEth) Backend() Backend { return self.eth }
func (self *XEth) UseState(statedb *state.StateDB) *XEth {
xeth := &XEth{
eth: self.eth,
blockProcessor: self.blockProcessor,
chainManager: self.chainManager,
whisper: self.whisper,
miner: self.miner,
}
xeth.state = NewState(xeth, statedb)
return xeth
}
func (self *XEth) State() *State { return self.state }
func (self *XEth) Whisper() *Whisper { return self.whisper }
func (self *XEth) Miner() *miner.Miner { return self.miner }
@ -229,7 +243,7 @@ func (self *XEth) Call(toStr, valueStr, gasStr, gasPriceStr, dataStr string) (st
}
var (
statedb = self.chainManager.TransState()
statedb = self.State().State() //self.chainManager.TransState()
key = self.eth.KeyManager().KeyPair()
from = statedb.GetOrNewStateObject(key.Address())
block = self.chainManager.CurrentBlock()