Compare commits
36 Commits
release/1.
...
v1.0.0
Author | SHA1 | Date | |
---|---|---|---|
0cdc7647aa | |||
c5d7faefe9 | |||
d7211dec79 | |||
cea2c0eedf | |||
b738172dcc | |||
abdc3d3c77 | |||
80901e8288 | |||
465796c3a8 | |||
9c05284bd1 | |||
56edaa1653 | |||
8865fda872 | |||
b0df9b164c | |||
72188234aa | |||
8c0619d29c | |||
16a3a4303f | |||
eaed7584f1 | |||
0262ba58cb | |||
e088998867 | |||
db5ec711e8 | |||
9d49c80783 | |||
b1fdb9f38e | |||
a606dc274b | |||
c9d6fba07d | |||
228fc5a83a | |||
c28dc03f6d | |||
dcb276a0dd | |||
53864a73db | |||
cf65a127e1 | |||
fd64dce6a5 | |||
d60b07249c | |||
7b99278eb0 | |||
aaf8ae1d0b | |||
a83fdd0046 | |||
b1a219b0ec | |||
487b3b0f7b | |||
4ca3d49307 |
@ -1,6 +1,9 @@
|
||||
language: go
|
||||
go:
|
||||
- 1.4.2
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -yqq libgmp3-dev
|
||||
install:
|
||||
# - go get code.google.com/p/go.tools/cmd/goimports
|
||||
# - go get github.com/golang/lint/golint
|
||||
@ -19,11 +22,7 @@ after_success:
|
||||
env:
|
||||
global:
|
||||
- secure: "U2U1AmkU4NJBgKR/uUAebQY87cNL0+1JHjnLOmmXwxYYyj5ralWb1aSuSH3qSXiT93qLBmtaUkuv9fberHVqrbAeVlztVdUsKAq7JMQH+M99iFkC9UiRMqHmtjWJ0ok4COD1sRYixxi21wb/JrMe3M1iL4QJVS61iltjHhVdM64="
|
||||
sudo: false
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libgmp3-dev
|
||||
|
||||
notifications:
|
||||
webhooks:
|
||||
urls:
|
||||
|
4
Godeps/_workspace/src/github.com/huin/goupnp/httpu/httpu.go
generated
vendored
4
Godeps/_workspace/src/github.com/huin/goupnp/httpu/httpu.go
generated
vendored
@ -9,8 +9,6 @@ import (
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/fdtrack"
|
||||
)
|
||||
|
||||
// HTTPUClient is a client for dealing with HTTPU (HTTP over UDP). Its typical
|
||||
@ -27,7 +25,6 @@ func NewHTTPUClient() (*HTTPUClient, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fdtrack.Open("upnp")
|
||||
return &HTTPUClient{conn: conn}, nil
|
||||
}
|
||||
|
||||
@ -36,7 +33,6 @@ func NewHTTPUClient() (*HTTPUClient, error) {
|
||||
func (httpu *HTTPUClient) Close() error {
|
||||
httpu.connLock.Lock()
|
||||
defer httpu.connLock.Unlock()
|
||||
fdtrack.Close("upnp")
|
||||
return httpu.conn.Close()
|
||||
}
|
||||
|
||||
|
14
Godeps/_workspace/src/github.com/huin/goupnp/soap/soap.go
generated
vendored
14
Godeps/_workspace/src/github.com/huin/goupnp/soap/soap.go
generated
vendored
@ -7,12 +7,9 @@ import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
|
||||
"github.com/ethereum/go-ethereum/fdtrack"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -29,17 +26,6 @@ type SOAPClient struct {
|
||||
func NewSOAPClient(endpointURL url.URL) *SOAPClient {
|
||||
return &SOAPClient{
|
||||
EndpointURL: endpointURL,
|
||||
HTTPClient: http.Client{
|
||||
Transport: &http.Transport{
|
||||
Dial: func(network, addr string) (net.Conn, error) {
|
||||
c, err := net.Dial(network, addr)
|
||||
if c != nil {
|
||||
c = fdtrack.WrapConn("upnp", c)
|
||||
}
|
||||
return c, err
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
4
Godeps/_workspace/src/github.com/jackpal/go-nat-pmp/natpmp.go
generated
vendored
4
Godeps/_workspace/src/github.com/jackpal/go-nat-pmp/natpmp.go
generated
vendored
@ -5,8 +5,6 @@ import (
|
||||
"log"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/fdtrack"
|
||||
)
|
||||
|
||||
// Implement the NAT-PMP protocol, typically supported by Apple routers and open source
|
||||
@ -104,8 +102,6 @@ func (n *Client) rpc(msg []byte, resultSize int) (result []byte, err error) {
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fdtrack.Open("natpmp")
|
||||
defer fdtrack.Close("natpmp")
|
||||
defer conn.Close()
|
||||
|
||||
result = make([]byte, resultSize)
|
||||
|
5
Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/file_storage.go
generated
vendored
5
Godeps/_workspace/src/github.com/syndtr/goleveldb/leveldb/storage/file_storage.go
generated
vendored
@ -18,7 +18,6 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/fdtrack"
|
||||
"github.com/syndtr/goleveldb/leveldb/util"
|
||||
)
|
||||
|
||||
@ -370,8 +369,6 @@ func (fw fileWrap) Close() error {
|
||||
err := fw.File.Close()
|
||||
if err != nil {
|
||||
f.fs.log(fmt.Sprintf("close %s.%d: %v", f.Type(), f.Num(), err))
|
||||
} else {
|
||||
fdtrack.Close("leveldb")
|
||||
}
|
||||
return err
|
||||
}
|
||||
@ -403,7 +400,6 @@ func (f *file) Open() (Reader, error) {
|
||||
return nil, err
|
||||
}
|
||||
ok:
|
||||
fdtrack.Open("leveldb")
|
||||
f.open = true
|
||||
f.fs.open++
|
||||
return fileWrap{of, f}, nil
|
||||
@ -422,7 +418,6 @@ func (f *file) Create() (Writer, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fdtrack.Open("leveldb")
|
||||
f.open = true
|
||||
f.fs.open++
|
||||
return fileWrap{of, f}, nil
|
||||
|
@ -78,8 +78,8 @@ func (am *Manager) DeleteAccount(address common.Address, auth string) error {
|
||||
|
||||
func (am *Manager) Sign(a Account, toSign []byte) (signature []byte, err error) {
|
||||
am.mutex.RLock()
|
||||
defer am.mutex.RUnlock()
|
||||
unlockedKey, found := am.unlocked[a.Address]
|
||||
am.mutex.RUnlock()
|
||||
if !found {
|
||||
return nil, ErrLocked
|
||||
}
|
||||
@ -87,17 +87,14 @@ func (am *Manager) Sign(a Account, toSign []byte) (signature []byte, err error)
|
||||
return signature, err
|
||||
}
|
||||
|
||||
// Unlock unlocks the given account indefinitely.
|
||||
// unlock indefinitely
|
||||
func (am *Manager) Unlock(addr common.Address, keyAuth string) error {
|
||||
return am.TimedUnlock(addr, keyAuth, 0)
|
||||
}
|
||||
|
||||
// TimedUnlock unlocks the account with the given address. The account
|
||||
// stays unlocked for the duration of timeout. A timeout of 0 unlocks the account
|
||||
// until the program exits.
|
||||
//
|
||||
// If the accout is already unlocked, TimedUnlock extends or shortens
|
||||
// the active unlock timeout.
|
||||
// Unlock unlocks the account with the given address. The account
|
||||
// stays unlocked for the duration of timeout
|
||||
// it timeout is 0 the account is unlocked for the entire session
|
||||
func (am *Manager) TimedUnlock(addr common.Address, keyAuth string, timeout time.Duration) error {
|
||||
key, err := am.keyStore.GetKey(addr, keyAuth)
|
||||
if err != nil {
|
||||
|
@ -23,10 +23,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/crypto/randentropy"
|
||||
)
|
||||
|
||||
var testSigData = make([]byte, 32)
|
||||
|
||||
func TestSign(t *testing.T) {
|
||||
dir, ks := tmpKeyStore(t, crypto.NewKeyStorePlain)
|
||||
defer os.RemoveAll(dir)
|
||||
@ -34,24 +33,26 @@ func TestSign(t *testing.T) {
|
||||
am := NewManager(ks)
|
||||
pass := "" // not used but required by API
|
||||
a1, err := am.NewAccount(pass)
|
||||
toSign := randentropy.GetEntropyCSPRNG(32)
|
||||
am.Unlock(a1.Address, "")
|
||||
|
||||
_, err = am.Sign(a1, testSigData)
|
||||
_, err = am.Sign(a1, toSign)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTimedUnlock(t *testing.T) {
|
||||
dir, ks := tmpKeyStore(t, crypto.NewKeyStorePlain)
|
||||
dir, ks := tmpKeyStore(t, crypto.NewKeyStorePassphrase)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
am := NewManager(ks)
|
||||
pass := "foo"
|
||||
a1, err := am.NewAccount(pass)
|
||||
toSign := randentropy.GetEntropyCSPRNG(32)
|
||||
|
||||
// Signing without passphrase fails because account is locked
|
||||
_, err = am.Sign(a1, testSigData)
|
||||
_, err = am.Sign(a1, toSign)
|
||||
if err != ErrLocked {
|
||||
t.Fatal("Signing should've failed with ErrLocked before unlocking, got ", err)
|
||||
}
|
||||
@ -62,26 +63,28 @@ func TestTimedUnlock(t *testing.T) {
|
||||
}
|
||||
|
||||
// Signing without passphrase works because account is temp unlocked
|
||||
_, err = am.Sign(a1, testSigData)
|
||||
_, err = am.Sign(a1, toSign)
|
||||
if err != nil {
|
||||
t.Fatal("Signing shouldn't return an error after unlocking, got ", err)
|
||||
}
|
||||
|
||||
// Signing fails again after automatic locking
|
||||
time.Sleep(150 * time.Millisecond)
|
||||
_, err = am.Sign(a1, testSigData)
|
||||
_, err = am.Sign(a1, toSign)
|
||||
if err != ErrLocked {
|
||||
t.Fatal("Signing should've failed with ErrLocked timeout expired, got ", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestOverrideUnlock(t *testing.T) {
|
||||
dir, ks := tmpKeyStore(t, crypto.NewKeyStorePlain)
|
||||
dir, ks := tmpKeyStore(t, crypto.NewKeyStorePassphrase)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
am := NewManager(ks)
|
||||
pass := "foo"
|
||||
a1, err := am.NewAccount(pass)
|
||||
toSign := randentropy.GetEntropyCSPRNG(32)
|
||||
|
||||
// Unlock indefinitely
|
||||
if err = am.Unlock(a1.Address, pass); err != nil {
|
||||
@ -89,7 +92,7 @@ func TestOverrideUnlock(t *testing.T) {
|
||||
}
|
||||
|
||||
// Signing without passphrase works because account is temp unlocked
|
||||
_, err = am.Sign(a1, testSigData)
|
||||
_, err = am.Sign(a1, toSign)
|
||||
if err != nil {
|
||||
t.Fatal("Signing shouldn't return an error after unlocking, got ", err)
|
||||
}
|
||||
@ -100,46 +103,20 @@ func TestOverrideUnlock(t *testing.T) {
|
||||
}
|
||||
|
||||
// Signing without passphrase still works because account is temp unlocked
|
||||
_, err = am.Sign(a1, testSigData)
|
||||
_, err = am.Sign(a1, toSign)
|
||||
if err != nil {
|
||||
t.Fatal("Signing shouldn't return an error after unlocking, got ", err)
|
||||
}
|
||||
|
||||
// Signing fails again after automatic locking
|
||||
time.Sleep(150 * time.Millisecond)
|
||||
_, err = am.Sign(a1, testSigData)
|
||||
_, err = am.Sign(a1, toSign)
|
||||
if err != ErrLocked {
|
||||
t.Fatal("Signing should've failed with ErrLocked timeout expired, got ", err)
|
||||
}
|
||||
}
|
||||
|
||||
// This test should fail under -race if signing races the expiration goroutine.
|
||||
func TestSignRace(t *testing.T) {
|
||||
dir, ks := tmpKeyStore(t, crypto.NewKeyStorePlain)
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
// Create a test account.
|
||||
am := NewManager(ks)
|
||||
a1, err := am.NewAccount("")
|
||||
if err != nil {
|
||||
t.Fatal("could not create the test account", err)
|
||||
}
|
||||
|
||||
if err := am.TimedUnlock(a1.Address, "", 15*time.Millisecond); err != nil {
|
||||
t.Fatalf("could not unlock the test account", err)
|
||||
}
|
||||
end := time.Now().Add(500 * time.Millisecond)
|
||||
for time.Now().Before(end) {
|
||||
if _, err := am.Sign(a1, testSigData); err == ErrLocked {
|
||||
return
|
||||
} else if err != nil {
|
||||
t.Errorf("Sign error: %v", err)
|
||||
return
|
||||
}
|
||||
time.Sleep(1 * time.Millisecond)
|
||||
}
|
||||
t.Errorf("Account did not lock within the timeout")
|
||||
}
|
||||
//
|
||||
|
||||
func tmpKeyStore(t *testing.T, new func(string) crypto.KeyStore) (string, crypto.KeyStore) {
|
||||
d, err := ioutil.TempDir("", "eth-keystore-test")
|
||||
|
@ -36,7 +36,6 @@ var (
|
||||
defaultTest = "all"
|
||||
defaultDir = "."
|
||||
allTests = []string{"BlockTests", "StateTests", "TransactionTests", "VMTests", "RLPTests"}
|
||||
testDirMapping = map[string]string{"BlockTests": "BlockchainTests"}
|
||||
skipTests = []string{}
|
||||
|
||||
TestFlag = cli.StringFlag{
|
||||
@ -136,13 +135,8 @@ func runSuite(test, file string) {
|
||||
var err error
|
||||
var files []string
|
||||
if test == defaultTest {
|
||||
// check if we have an explicit directory mapping for the test
|
||||
if _, ok := testDirMapping[curTest]; ok {
|
||||
files, err = getFiles(filepath.Join(file, testDirMapping[curTest]))
|
||||
} else {
|
||||
// otherwise assume test name
|
||||
files, err = getFiles(filepath.Join(file, curTest))
|
||||
}
|
||||
files, err = getFiles(filepath.Join(file, curTest))
|
||||
|
||||
} else {
|
||||
files, err = getFiles(file)
|
||||
}
|
||||
|
118
cmd/evm/main.go
118
cmd/evm/main.go
@ -18,129 +18,79 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"math/big"
|
||||
"os"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/codegangsta/cli"
|
||||
"github.com/ethereum/go-ethereum/cmd/utils"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/state"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/core/vm"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
app *cli.App
|
||||
DebugFlag = cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Usage: "output full trace logs",
|
||||
}
|
||||
CodeFlag = cli.StringFlag{
|
||||
Name: "code",
|
||||
Usage: "EVM code",
|
||||
}
|
||||
GasFlag = cli.StringFlag{
|
||||
Name: "gas",
|
||||
Usage: "gas limit for the evm",
|
||||
Value: "10000000000",
|
||||
}
|
||||
PriceFlag = cli.StringFlag{
|
||||
Name: "price",
|
||||
Usage: "price set for the evm",
|
||||
Value: "0",
|
||||
}
|
||||
ValueFlag = cli.StringFlag{
|
||||
Name: "value",
|
||||
Usage: "value set for the evm",
|
||||
Value: "0",
|
||||
}
|
||||
DumpFlag = cli.BoolFlag{
|
||||
Name: "dump",
|
||||
Usage: "dumps the state after the run",
|
||||
}
|
||||
InputFlag = cli.StringFlag{
|
||||
Name: "input",
|
||||
Usage: "input for the EVM",
|
||||
}
|
||||
SysStatFlag = cli.BoolFlag{
|
||||
Name: "sysstat",
|
||||
Usage: "display system stats",
|
||||
}
|
||||
code = flag.String("code", "", "evm code")
|
||||
loglevel = flag.Int("log", 4, "log level")
|
||||
gas = flag.String("gas", "1000000000", "gas amount")
|
||||
price = flag.String("price", "0", "gas price")
|
||||
value = flag.String("value", "0", "tx value")
|
||||
dump = flag.Bool("dump", false, "dump state after run")
|
||||
data = flag.String("data", "", "data")
|
||||
)
|
||||
|
||||
func init() {
|
||||
app = utils.NewApp("0.2", "the evm command line interface")
|
||||
app.Flags = []cli.Flag{
|
||||
DebugFlag,
|
||||
SysStatFlag,
|
||||
CodeFlag,
|
||||
GasFlag,
|
||||
PriceFlag,
|
||||
ValueFlag,
|
||||
DumpFlag,
|
||||
InputFlag,
|
||||
}
|
||||
app.Action = run
|
||||
func perr(v ...interface{}) {
|
||||
fmt.Println(v...)
|
||||
//os.Exit(1)
|
||||
}
|
||||
|
||||
func run(ctx *cli.Context) {
|
||||
vm.Debug = ctx.GlobalBool(DebugFlag.Name)
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, log.LstdFlags, logger.LogLevel(*loglevel)))
|
||||
|
||||
vm.Debug = true
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
statedb := state.New(common.Hash{}, db)
|
||||
sender := statedb.CreateAccount(common.StringToAddress("sender"))
|
||||
receiver := statedb.CreateAccount(common.StringToAddress("receiver"))
|
||||
receiver.SetCode(common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name)))
|
||||
receiver.SetCode(common.Hex2Bytes(*code))
|
||||
|
||||
vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(ctx.GlobalString(ValueFlag.Name)))
|
||||
vmenv := NewEnv(statedb, common.StringToAddress("evmuser"), common.Big(*value))
|
||||
|
||||
tstart := time.Now()
|
||||
ret, e := vmenv.Call(
|
||||
sender,
|
||||
receiver.Address(),
|
||||
common.Hex2Bytes(ctx.GlobalString(InputFlag.Name)),
|
||||
common.Big(ctx.GlobalString(GasFlag.Name)),
|
||||
common.Big(ctx.GlobalString(PriceFlag.Name)),
|
||||
common.Big(ctx.GlobalString(ValueFlag.Name)),
|
||||
)
|
||||
vmdone := time.Since(tstart)
|
||||
|
||||
ret, e := vmenv.Call(sender, receiver.Address(), common.Hex2Bytes(*data), common.Big(*gas), common.Big(*price), common.Big(*value))
|
||||
|
||||
logger.Flush()
|
||||
if e != nil {
|
||||
fmt.Println(e)
|
||||
os.Exit(1)
|
||||
perr(e)
|
||||
}
|
||||
|
||||
if ctx.GlobalBool(DumpFlag.Name) {
|
||||
if *dump {
|
||||
fmt.Println(string(statedb.Dump()))
|
||||
}
|
||||
|
||||
vm.StdErrFormat(vmenv.StructLogs())
|
||||
|
||||
if ctx.GlobalBool(SysStatFlag.Name) {
|
||||
var mem runtime.MemStats
|
||||
runtime.ReadMemStats(&mem)
|
||||
fmt.Printf("vm took %v\n", vmdone)
|
||||
fmt.Printf(`alloc: %d
|
||||
var mem runtime.MemStats
|
||||
runtime.ReadMemStats(&mem)
|
||||
fmt.Printf("vm took %v\n", time.Since(tstart))
|
||||
fmt.Printf(`alloc: %d
|
||||
tot alloc: %d
|
||||
no. malloc: %d
|
||||
heap alloc: %d
|
||||
heap objs: %d
|
||||
num gc: %d
|
||||
`, mem.Alloc, mem.TotalAlloc, mem.Mallocs, mem.HeapAlloc, mem.HeapObjects, mem.NumGC)
|
||||
}
|
||||
|
||||
fmt.Printf("OUT: 0x%x\n", ret)
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("%x\n", ret)
|
||||
}
|
||||
|
||||
type VMEnv struct {
|
||||
@ -152,7 +102,7 @@ type VMEnv struct {
|
||||
|
||||
depth int
|
||||
Gas *big.Int
|
||||
time *big.Int
|
||||
time uint64
|
||||
logs []vm.StructLog
|
||||
}
|
||||
|
||||
@ -161,7 +111,7 @@ func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int) *VM
|
||||
state: state,
|
||||
transactor: &transactor,
|
||||
value: value,
|
||||
time: big.NewInt(time.Now().Unix()),
|
||||
time: uint64(time.Now().Unix()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,7 +119,7 @@ func (self *VMEnv) State() *state.StateDB { return self.state }
|
||||
func (self *VMEnv) Origin() common.Address { return *self.transactor }
|
||||
func (self *VMEnv) BlockNumber() *big.Int { return common.Big0 }
|
||||
func (self *VMEnv) Coinbase() common.Address { return *self.transactor }
|
||||
func (self *VMEnv) Time() *big.Int { return self.time }
|
||||
func (self *VMEnv) Time() uint64 { return self.time }
|
||||
func (self *VMEnv) Difficulty() *big.Int { return common.Big1 }
|
||||
func (self *VMEnv) BlockHash() []byte { return make([]byte, 32) }
|
||||
func (self *VMEnv) Value() *big.Int { return self.value }
|
||||
|
@ -23,7 +23,6 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"sort"
|
||||
@ -45,10 +44,6 @@ import (
|
||||
"github.com/robertkrimen/otto"
|
||||
)
|
||||
|
||||
var passwordRegexp = regexp.MustCompile("personal.[nu]")
|
||||
|
||||
const passwordRepl = ""
|
||||
|
||||
type prompter interface {
|
||||
AppendHistory(string)
|
||||
Prompt(p string) (string, error)
|
||||
@ -418,10 +413,8 @@ func (self *jsre) interactive() {
|
||||
str += input + "\n"
|
||||
self.setIndent()
|
||||
if indentCount <= 0 {
|
||||
hist := hidepassword(str[:len(str)-1])
|
||||
if len(hist) > 0 {
|
||||
self.AppendHistory(hist)
|
||||
}
|
||||
hist := str[:len(str)-1]
|
||||
self.AppendHistory(hist)
|
||||
self.parseInput(str)
|
||||
str = ""
|
||||
}
|
||||
@ -429,14 +422,6 @@ func (self *jsre) interactive() {
|
||||
}
|
||||
}
|
||||
|
||||
func hidepassword(input string) string {
|
||||
if passwordRegexp.MatchString(input) {
|
||||
return passwordRepl
|
||||
} else {
|
||||
return input
|
||||
}
|
||||
}
|
||||
|
||||
func (self *jsre) withHistory(op func(*os.File)) {
|
||||
datadir := common.DefaultDataDir()
|
||||
if self.ethereum != nil {
|
||||
|
@ -38,7 +38,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/fdtrack"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
"github.com/ethereum/go-ethereum/metrics"
|
||||
@ -50,7 +49,7 @@ import (
|
||||
|
||||
const (
|
||||
ClientIdentifier = "Geth"
|
||||
Version = "1.0.6"
|
||||
Version = "1.0.0"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -281,8 +280,6 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
|
||||
utils.BootnodesFlag,
|
||||
utils.DataDirFlag,
|
||||
utils.BlockchainVersionFlag,
|
||||
utils.OlympicFlag,
|
||||
utils.CacheFlag,
|
||||
utils.JSpathFlag,
|
||||
utils.ListenPortFlag,
|
||||
utils.MaxPeersFlag,
|
||||
@ -348,9 +345,6 @@ func main() {
|
||||
|
||||
func run(ctx *cli.Context) {
|
||||
utils.CheckLegalese(ctx.GlobalString(utils.DataDirFlag.Name))
|
||||
if ctx.GlobalBool(utils.OlympicFlag.Name) {
|
||||
utils.InitOlympic()
|
||||
}
|
||||
|
||||
cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
|
||||
ethereum, err := eth.New(cfg)
|
||||
@ -506,7 +500,7 @@ func blockRecovery(ctx *cli.Context) {
|
||||
cfg := utils.MakeEthConfig(ClientIdentifier, nodeNameVersion, ctx)
|
||||
utils.CheckLegalese(cfg.DataDir)
|
||||
|
||||
blockDb, err := ethdb.NewLDBDatabase(filepath.Join(cfg.DataDir, "blockchain"), cfg.DatabaseCache)
|
||||
blockDb, err := ethdb.NewLDBDatabase(filepath.Join(cfg.DataDir, "blockchain"))
|
||||
if err != nil {
|
||||
glog.Fatalln("could not open db:", err)
|
||||
}
|
||||
@ -533,9 +527,6 @@ func startEth(ctx *cli.Context, eth *eth.Ethereum) {
|
||||
// Start Ethereum itself
|
||||
utils.StartEthereum(eth)
|
||||
|
||||
// Start logging file descriptor stats.
|
||||
fdtrack.Start()
|
||||
|
||||
am := eth.AccountManager()
|
||||
account := ctx.GlobalString(utils.UnlockedAccountFlag.Name)
|
||||
accounts := strings.Split(account, " ")
|
||||
|
@ -21,7 +21,6 @@ import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"os"
|
||||
"os/signal"
|
||||
"regexp"
|
||||
@ -33,7 +32,6 @@ import (
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/peterh/liner"
|
||||
)
|
||||
@ -145,15 +143,6 @@ func StartEthereum(ethereum *eth.Ethereum) {
|
||||
}()
|
||||
}
|
||||
|
||||
func InitOlympic() {
|
||||
params.DurationLimit = big.NewInt(8)
|
||||
params.GenesisGasLimit = big.NewInt(3141592)
|
||||
params.MinGasLimit = big.NewInt(125000)
|
||||
params.MaximumExtraDataSize = big.NewInt(1024)
|
||||
NetworkIdFlag.Value = 0
|
||||
core.BlockReward = big.NewInt(1.5e+18)
|
||||
}
|
||||
|
||||
func FormatTransactionData(data string) []byte {
|
||||
d := common.StringToByteFunc(data, func(s string) (ret []byte) {
|
||||
slice := regexp.MustCompile("\\n|\\s").Split(s, 1000000000)
|
||||
@ -214,11 +203,6 @@ func ImportChain(chain *core.ChainManager, fn string) error {
|
||||
} else if err != nil {
|
||||
return fmt.Errorf("at block %d: %v", n, err)
|
||||
}
|
||||
// don't import first block
|
||||
if b.NumberU64() == 0 {
|
||||
i--
|
||||
continue
|
||||
}
|
||||
blocks[i] = &b
|
||||
n++
|
||||
}
|
||||
@ -234,7 +218,6 @@ func ImportChain(chain *core.ChainManager, fn string) error {
|
||||
batch, blocks[0].Hash().Bytes()[:4], blocks[i-1].Hash().Bytes()[:4])
|
||||
continue
|
||||
}
|
||||
|
||||
if _, err := chain.InsertChain(blocks[:i]); err != nil {
|
||||
return fmt.Errorf("invalid block %d: %v", n, err)
|
||||
}
|
||||
|
@ -126,15 +126,6 @@ var (
|
||||
Name: "natspec",
|
||||
Usage: "Enable NatSpec confirmation notice",
|
||||
}
|
||||
CacheFlag = cli.IntFlag{
|
||||
Name: "cache",
|
||||
Usage: "Megabytes of memory allocated to internal caching",
|
||||
Value: 0,
|
||||
}
|
||||
OlympicFlag = cli.BoolFlag{
|
||||
Name: "olympic",
|
||||
Usage: "Use olympic style protocol",
|
||||
}
|
||||
|
||||
// miner settings
|
||||
MinerThreadsFlag = cli.IntFlag{
|
||||
@ -158,7 +149,7 @@ var (
|
||||
GasPriceFlag = cli.StringFlag{
|
||||
Name: "gasprice",
|
||||
Usage: "Sets the minimal gasprice when mining transactions",
|
||||
Value: new(big.Int).Mul(big.NewInt(50), common.Shannon).String(),
|
||||
Value: new(big.Int).Mul(big.NewInt(500), common.Shannon).String(),
|
||||
}
|
||||
|
||||
UnlockedAccountFlag = cli.StringFlag{
|
||||
@ -318,12 +309,12 @@ var (
|
||||
GpoMinGasPriceFlag = cli.StringFlag{
|
||||
Name: "gpomin",
|
||||
Usage: "Minimum suggested gas price",
|
||||
Value: new(big.Int).Mul(big.NewInt(50), common.Shannon).String(),
|
||||
Value: new(big.Int).Mul(big.NewInt(1), common.Szabo).String(),
|
||||
}
|
||||
GpoMaxGasPriceFlag = cli.StringFlag{
|
||||
Name: "gpomax",
|
||||
Usage: "Maximum suggested gas price",
|
||||
Value: new(big.Int).Mul(big.NewInt(500), common.Shannon).String(),
|
||||
Value: new(big.Int).Mul(big.NewInt(100), common.Szabo).String(),
|
||||
}
|
||||
GpoFullBlockRatioFlag = cli.IntFlag{
|
||||
Name: "gpofull",
|
||||
@ -393,7 +384,6 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
|
||||
GenesisNonce: ctx.GlobalInt(GenesisNonceFlag.Name),
|
||||
GenesisFile: ctx.GlobalString(GenesisFileFlag.Name),
|
||||
BlockChainVersion: ctx.GlobalInt(BlockchainVersionFlag.Name),
|
||||
DatabaseCache: ctx.GlobalInt(CacheFlag.Name),
|
||||
SkipBcVersionCheck: false,
|
||||
NetworkId: ctx.GlobalInt(NetworkIdFlag.Name),
|
||||
LogFile: ctx.GlobalString(LogFileFlag.Name),
|
||||
@ -406,7 +396,6 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
|
||||
MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name),
|
||||
MaxPendingPeers: ctx.GlobalInt(MaxPendingPeersFlag.Name),
|
||||
Port: ctx.GlobalString(ListenPortFlag.Name),
|
||||
Olympic: ctx.GlobalBool(OlympicFlag.Name),
|
||||
NAT: MakeNAT(ctx),
|
||||
NatSpec: ctx.GlobalBool(NatspecEnabledFlag.Name),
|
||||
Discovery: !ctx.GlobalBool(NoDiscoverFlag.Name),
|
||||
@ -436,26 +425,17 @@ func SetupLogger(ctx *cli.Context) {
|
||||
|
||||
// MakeChain creates a chain manager from set command line flags.
|
||||
func MakeChain(ctx *cli.Context) (chain *core.ChainManager, blockDB, stateDB, extraDB common.Database) {
|
||||
datadir := ctx.GlobalString(DataDirFlag.Name)
|
||||
cache := ctx.GlobalInt(CacheFlag.Name)
|
||||
|
||||
dd := ctx.GlobalString(DataDirFlag.Name)
|
||||
var err error
|
||||
if blockDB, err = ethdb.NewLDBDatabase(filepath.Join(datadir, "blockchain"), cache); err != nil {
|
||||
if blockDB, err = ethdb.NewLDBDatabase(filepath.Join(dd, "blockchain")); err != nil {
|
||||
Fatalf("Could not open database: %v", err)
|
||||
}
|
||||
if stateDB, err = ethdb.NewLDBDatabase(filepath.Join(datadir, "state"), cache); err != nil {
|
||||
if stateDB, err = ethdb.NewLDBDatabase(filepath.Join(dd, "state")); err != nil {
|
||||
Fatalf("Could not open database: %v", err)
|
||||
}
|
||||
if extraDB, err = ethdb.NewLDBDatabase(filepath.Join(datadir, "extra"), cache); err != nil {
|
||||
if extraDB, err = ethdb.NewLDBDatabase(filepath.Join(dd, "extra")); err != nil {
|
||||
Fatalf("Could not open database: %v", err)
|
||||
}
|
||||
if ctx.GlobalBool(OlympicFlag.Name) {
|
||||
InitOlympic()
|
||||
_, err := core.WriteTestNetGenesisBlock(stateDB, blockDB, 42)
|
||||
if err != nil {
|
||||
glog.Fatalln(err)
|
||||
}
|
||||
}
|
||||
|
||||
eventMux := new(event.TypeMux)
|
||||
pow := ethash.New()
|
||||
|
@ -153,7 +153,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
|
||||
b.Fatalf("cannot create temporary directory: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
db, err = ethdb.NewLDBDatabase(dir, 0)
|
||||
db, err = ethdb.NewLDBDatabase(dir)
|
||||
if err != nil {
|
||||
b.Fatalf("cannot create temporary database: %v", err)
|
||||
}
|
||||
|
@ -57,18 +57,6 @@ type BlockProcessor struct {
|
||||
eventMux *event.TypeMux
|
||||
}
|
||||
|
||||
// TODO: type GasPool big.Int
|
||||
//
|
||||
// GasPool is implemented by state.StateObject. This is a historical
|
||||
// coincidence. Gas tracking should move out of StateObject.
|
||||
|
||||
// GasPool tracks the amount of gas available during
|
||||
// execution of the transactions in a block.
|
||||
type GasPool interface {
|
||||
AddGas(gas, price *big.Int)
|
||||
SubGas(gas, price *big.Int) error
|
||||
}
|
||||
|
||||
func NewBlockProcessor(db, extra common.Database, pow pow.PoW, chainManager *ChainManager, eventMux *event.TypeMux) *BlockProcessor {
|
||||
sm := &BlockProcessor{
|
||||
db: db,
|
||||
@ -78,15 +66,16 @@ func NewBlockProcessor(db, extra common.Database, pow pow.PoW, chainManager *Cha
|
||||
bc: chainManager,
|
||||
eventMux: eventMux,
|
||||
}
|
||||
|
||||
return sm
|
||||
}
|
||||
|
||||
func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block *types.Block, transientProcess bool) (receipts types.Receipts, err error) {
|
||||
gp := statedb.GetOrNewStateObject(block.Coinbase())
|
||||
gp.SetGasLimit(block.GasLimit())
|
||||
coinbase := statedb.GetOrNewStateObject(block.Coinbase())
|
||||
coinbase.SetGasLimit(block.GasLimit())
|
||||
|
||||
// Process the transactions on to parent state
|
||||
receipts, err = sm.ApplyTransactions(gp, statedb, block, block.Transactions(), transientProcess)
|
||||
receipts, err = sm.ApplyTransactions(coinbase, statedb, block, block.Transactions(), transientProcess)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -94,8 +83,11 @@ func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block
|
||||
return receipts, nil
|
||||
}
|
||||
|
||||
func (self *BlockProcessor) ApplyTransaction(gp GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) {
|
||||
_, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, header), tx, gp)
|
||||
func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) {
|
||||
// If we are mining this block and validating we want to set the logs back to 0
|
||||
|
||||
cb := statedb.GetStateObject(coinbase.Address())
|
||||
_, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, header), tx, cb)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -130,7 +122,7 @@ func (self *BlockProcessor) ChainManager() *ChainManager {
|
||||
return self.bc
|
||||
}
|
||||
|
||||
func (self *BlockProcessor) ApplyTransactions(gp GasPool, statedb *state.StateDB, block *types.Block, txs types.Transactions, transientProcess bool) (types.Receipts, error) {
|
||||
func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, statedb *state.StateDB, block *types.Block, txs types.Transactions, transientProcess bool) (types.Receipts, error) {
|
||||
var (
|
||||
receipts types.Receipts
|
||||
totalUsedGas = big.NewInt(0)
|
||||
@ -142,7 +134,7 @@ func (self *BlockProcessor) ApplyTransactions(gp GasPool, statedb *state.StateDB
|
||||
for i, tx := range txs {
|
||||
statedb.StartRecord(tx.Hash(), block.Hash(), i)
|
||||
|
||||
receipt, txGas, err := self.ApplyTransaction(gp, statedb, header, tx, totalUsedGas, transientProcess)
|
||||
receipt, txGas, err := self.ApplyTransaction(coinbase, statedb, header, tx, totalUsedGas, transientProcess)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -215,7 +207,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
|
||||
txs := block.Transactions()
|
||||
|
||||
// Block validation
|
||||
if err = ValidateHeader(sm.Pow, header, parent, false, false); err != nil {
|
||||
if err = ValidateHeader(sm.Pow, header, parent, false); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@ -339,7 +331,7 @@ func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *ty
|
||||
return UncleError("uncle[%d](%x)'s parent is not ancestor (%x)", i, hash[:4], uncle.ParentHash[0:4])
|
||||
}
|
||||
|
||||
if err := ValidateHeader(sm.Pow, uncle, ancestors[uncle.ParentHash], true, true); err != nil {
|
||||
if err := ValidateHeader(sm.Pow, uncle, ancestors[uncle.ParentHash], true); err != nil {
|
||||
return ValidationError(fmt.Sprintf("uncle[%d](%x) header invalid: %v", i, hash[:4], err))
|
||||
}
|
||||
}
|
||||
@ -382,25 +374,19 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro
|
||||
|
||||
// See YP section 4.3.4. "Block Header Validity"
|
||||
// Validates a block. Returns an error if the block is invalid.
|
||||
func ValidateHeader(pow pow.PoW, block *types.Header, parent *types.Block, checkPow, uncle bool) error {
|
||||
func ValidateHeader(pow pow.PoW, block *types.Header, parent *types.Block, checkPow bool) error {
|
||||
if big.NewInt(int64(len(block.Extra))).Cmp(params.MaximumExtraDataSize) == 1 {
|
||||
return fmt.Errorf("Block extra data too long (%d)", len(block.Extra))
|
||||
}
|
||||
|
||||
if uncle {
|
||||
if block.Time.Cmp(common.MaxBig) == 1 {
|
||||
return BlockTSTooBigErr
|
||||
}
|
||||
} else {
|
||||
if block.Time.Cmp(big.NewInt(time.Now().Unix())) == 1 {
|
||||
return BlockFutureErr
|
||||
}
|
||||
if block.Time > uint64(time.Now().Unix()) {
|
||||
return BlockFutureErr
|
||||
}
|
||||
if block.Time.Cmp(parent.Time()) != 1 {
|
||||
if block.Time <= parent.Time() {
|
||||
return BlockEqualTSErr
|
||||
}
|
||||
|
||||
expd := CalcDifficulty(block.Time.Uint64(), parent.Time().Uint64(), parent.Number(), parent.Difficulty())
|
||||
expd := CalcDifficulty(block.Time, parent.Time(), parent.Difficulty())
|
||||
if expd.Cmp(block.Difficulty) != 0 {
|
||||
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd)
|
||||
}
|
||||
|
@ -48,13 +48,13 @@ func TestNumber(t *testing.T) {
|
||||
statedb := state.New(chain.Genesis().Root(), chain.stateDb)
|
||||
header := makeHeader(chain.Genesis(), statedb)
|
||||
header.Number = big.NewInt(3)
|
||||
err := ValidateHeader(pow, header, chain.Genesis(), false, false)
|
||||
err := ValidateHeader(pow, header, chain.Genesis(), false)
|
||||
if err != BlockNumberErr {
|
||||
t.Errorf("expected block number error, got %q", err)
|
||||
}
|
||||
|
||||
header = makeHeader(chain.Genesis(), statedb)
|
||||
err = ValidateHeader(pow, header, chain.Genesis(), false, false)
|
||||
err = ValidateHeader(pow, header, chain.Genesis(), false)
|
||||
if err == BlockNumberErr {
|
||||
t.Errorf("didn't expect block number error")
|
||||
}
|
||||
|
@ -20,5 +20,8 @@ import "github.com/ethereum/go-ethereum/common"
|
||||
|
||||
// Set of manually tracked bad hashes (usually hard forks)
|
||||
var BadHashes = map[common.Hash]bool{
|
||||
common.HexToHash("05bef30ef572270f654746da22639a7a0c97dd97a7050b9e252391996aaeb689"): true,
|
||||
common.HexToHash("f269c503aed286caaa0d114d6a5320e70abbc2febe37953207e76a2873f2ba79"): true,
|
||||
common.HexToHash("38f5bbbffd74804820ffa4bab0cd540e9de229725afb98c1a7e57936f4a714bc"): true,
|
||||
common.HexToHash("7064455b364775a16afbdecd75370e912c6e2879f202eda85b9beae547fff3ac"): true,
|
||||
common.HexToHash("5b7c80070a6eff35f3eb3181edb023465c776d40af2885571e1bc4689f3a44d8"): true,
|
||||
}
|
||||
|
@ -24,10 +24,10 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
jeff = common.HexToAddress("959c33de5961820567930eccce51ea715c496f85")
|
||||
vitalik = common.HexToAddress("c8158da0b567a8cc898991c2c2a073af67dc03a9")
|
||||
christoph = common.HexToAddress("7a19a893f91d5b6e2cdf941b6acbba2cbcf431ee")
|
||||
gav = common.HexToAddress("539dd9aaf45c3feb03f9c004f4098bd3268fef6b")
|
||||
jeff = common.HexToAddress("a8edb1ac2c86d3d9d78f96cd18001f60df29e52c")
|
||||
vitalik = common.HexToAddress("1baf27b88c48dd02b744999cf3522766929d2b2a")
|
||||
christoph = common.HexToAddress("60d11b58744784dc97f878f7e3749c0f1381a004")
|
||||
gav = common.HexToAddress("4bb7e8ae99b645c2b7860b8f3a2328aae28bd80a")
|
||||
)
|
||||
|
||||
// Canary will check the 0'd address of the 4 contracts above.
|
||||
|
@ -166,21 +166,16 @@ func GenerateChain(parent *types.Block, db common.Database, n int, gen func(int,
|
||||
}
|
||||
|
||||
func makeHeader(parent *types.Block, state *state.StateDB) *types.Header {
|
||||
var time *big.Int
|
||||
if parent.Time() == nil {
|
||||
time = big.NewInt(10)
|
||||
} else {
|
||||
time = new(big.Int).Add(parent.Time(), big.NewInt(10)) // block time is fixed at 10 seconds
|
||||
}
|
||||
time := parent.Time() + 10 // block time is fixed at 10 seconds
|
||||
return &types.Header{
|
||||
Root: state.Root(),
|
||||
ParentHash: parent.Hash(),
|
||||
Coinbase: parent.Coinbase(),
|
||||
Difficulty: CalcDifficulty(time.Uint64(), new(big.Int).Sub(time, big.NewInt(10)).Uint64(), parent.Number(), parent.Difficulty()),
|
||||
Difficulty: CalcDifficulty(time, parent.Time(), parent.Difficulty()),
|
||||
GasLimit: CalcGasLimit(parent),
|
||||
GasUsed: new(big.Int),
|
||||
Number: new(big.Int).Add(parent.Number(), common.Big1),
|
||||
Time: time,
|
||||
Time: uint64(time),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -73,11 +73,13 @@ type ChainManager struct {
|
||||
lastBlockHash common.Hash
|
||||
currentGasLimit *big.Int
|
||||
|
||||
transState *state.StateDB
|
||||
txState *state.ManagedState
|
||||
|
||||
cache *lru.Cache // cache is the LRU caching
|
||||
futureBlocks *lru.Cache // future blocks are blocks added for later processing
|
||||
|
||||
quit chan struct{}
|
||||
running int32 // running must be called automically
|
||||
quit chan struct{}
|
||||
// procInterrupt must be atomically called
|
||||
procInterrupt int32 // interrupt signaler for block processing
|
||||
wg sync.WaitGroup
|
||||
@ -99,15 +101,7 @@ func NewChainManager(blockDb, stateDb, extraDb common.Database, pow pow.PoW, mux
|
||||
|
||||
bc.genesisBlock = bc.GetBlockByNumber(0)
|
||||
if bc.genesisBlock == nil {
|
||||
reader, err := NewDefaultGenesisReader()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
bc.genesisBlock, err = WriteGenesisBlock(stateDb, blockDb, reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
glog.V(logger.Info).Infoln("WARNING: Wrote default ethereum genesis block")
|
||||
return nil, ErrNoGenesis
|
||||
}
|
||||
|
||||
if err := bc.setLastState(); err != nil {
|
||||
@ -128,7 +122,9 @@ func NewChainManager(blockDb, stateDb, extraDb common.Database, pow pow.PoW, mux
|
||||
}
|
||||
}
|
||||
|
||||
bc.transState = bc.State().Copy()
|
||||
// Take ownership of this particular state
|
||||
bc.txState = state.ManageState(bc.State().Copy())
|
||||
|
||||
bc.futureBlocks, _ = lru.New(maxFutureBlocks)
|
||||
bc.makeCache()
|
||||
@ -150,6 +146,9 @@ func (bc *ChainManager) SetHead(head *types.Block) {
|
||||
bc.currentBlock = head
|
||||
bc.makeCache()
|
||||
|
||||
statedb := state.New(head.Root(), bc.stateDb)
|
||||
bc.txState = state.ManageState(statedb)
|
||||
bc.transState = statedb.Copy()
|
||||
bc.setTotalDifficulty(head.Td)
|
||||
bc.insert(head)
|
||||
bc.setLastState()
|
||||
@ -198,6 +197,17 @@ func (self *ChainManager) State() *state.StateDB {
|
||||
return state.New(self.CurrentBlock().Root(), self.stateDb)
|
||||
}
|
||||
|
||||
func (self *ChainManager) TransState() *state.StateDB {
|
||||
self.tsmu.RLock()
|
||||
defer self.tsmu.RUnlock()
|
||||
|
||||
return self.transState
|
||||
}
|
||||
|
||||
func (self *ChainManager) setTransState(statedb *state.StateDB) {
|
||||
self.transState = statedb
|
||||
}
|
||||
|
||||
func (bc *ChainManager) recover() bool {
|
||||
data, _ := bc.blockDb.Get([]byte("checkpoint"))
|
||||
if len(data) != 0 {
|
||||
@ -452,9 +462,6 @@ func (bc *ChainManager) setTotalDifficulty(td *big.Int) {
|
||||
}
|
||||
|
||||
func (bc *ChainManager) Stop() {
|
||||
if !atomic.CompareAndSwapInt32(&bc.running, 0, 1) {
|
||||
return
|
||||
}
|
||||
close(bc.quit)
|
||||
atomic.StoreInt32(&bc.procInterrupt, 1)
|
||||
|
||||
@ -516,6 +523,9 @@ func (self *ChainManager) WriteBlock(block *types.Block, queued bool) (status wr
|
||||
self.insert(block)
|
||||
self.mu.Unlock()
|
||||
|
||||
self.setTransState(state.New(block.Root(), self.stateDb))
|
||||
self.txState.SetState(state.New(block.Root(), self.stateDb))
|
||||
|
||||
status = CanonStatTy
|
||||
} else {
|
||||
status = SideStatTy
|
||||
@ -600,8 +610,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
|
||||
// Allow up to MaxFuture second in the future blocks. If this limit
|
||||
// is exceeded the chain is discarded and processed at a later time
|
||||
// if given.
|
||||
max := big.NewInt(time.Now().Unix() + maxTimeFutureBlocks)
|
||||
if block.Time().Cmp(max) == 1 {
|
||||
if max := uint64(time.Now().Unix()) + maxTimeFutureBlocks; block.Time() > max {
|
||||
return i, fmt.Errorf("%v: BlockFutureErr, %v > %v", BlockFutureErr, block.Time(), max)
|
||||
}
|
||||
|
||||
|
@ -392,6 +392,7 @@ func chm(genesis *types.Block, db common.Database) *ChainManager {
|
||||
bc.futureBlocks, _ = lru.New(100)
|
||||
bc.processor = bproc{}
|
||||
bc.ResetWithGenesisBlock(genesis)
|
||||
bc.txState = state.ManageState(bc.State())
|
||||
|
||||
return bc
|
||||
}
|
||||
|
@ -30,15 +30,14 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
blockHashPre = []byte("block-hash-")
|
||||
blockNumPre = []byte("block-num-")
|
||||
expDiffPeriod = big.NewInt(100000)
|
||||
blockHashPre = []byte("block-hash-")
|
||||
blockNumPre = []byte("block-num-")
|
||||
)
|
||||
|
||||
// CalcDifficulty is the difficulty adjustment algorithm. It returns
|
||||
// the difficulty that a new block b should have when created at time
|
||||
// given the parent block's time and difficulty.
|
||||
func CalcDifficulty(time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
|
||||
func CalcDifficulty(time, parentTime uint64, parentDiff *big.Int) *big.Int {
|
||||
diff := new(big.Int)
|
||||
adjust := new(big.Int).Div(parentDiff, params.DifficultyBoundDivisor)
|
||||
bigTime := new(big.Int)
|
||||
@ -53,19 +52,8 @@ func CalcDifficulty(time, parentTime uint64, parentNumber, parentDiff *big.Int)
|
||||
diff.Sub(parentDiff, adjust)
|
||||
}
|
||||
if diff.Cmp(params.MinimumDifficulty) < 0 {
|
||||
diff = params.MinimumDifficulty
|
||||
return params.MinimumDifficulty
|
||||
}
|
||||
|
||||
periodCount := new(big.Int).Add(parentNumber, common.Big1)
|
||||
periodCount.Div(periodCount, expDiffPeriod)
|
||||
if periodCount.Cmp(common.Big1) > 0 {
|
||||
// diff = diff + 2^(periodCount - 2)
|
||||
expDiff := periodCount.Sub(periodCount, common.Big2)
|
||||
expDiff.Exp(common.Big2, expDiff, nil)
|
||||
diff.Add(diff, expDiff)
|
||||
diff = common.BigMax(diff, params.MinimumDifficulty)
|
||||
}
|
||||
|
||||
return diff
|
||||
}
|
||||
|
||||
@ -81,30 +69,17 @@ func CalcTD(block, parent *types.Block) *big.Int {
|
||||
|
||||
// CalcGasLimit computes the gas limit of the next block after parent.
|
||||
// The result may be modified by the caller.
|
||||
// This is miner strategy, not consensus protocol.
|
||||
func CalcGasLimit(parent *types.Block) *big.Int {
|
||||
// contrib = (parentGasUsed * 3 / 2) / 1024
|
||||
decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor)
|
||||
contrib := new(big.Int).Mul(parent.GasUsed(), big.NewInt(3))
|
||||
contrib = contrib.Div(contrib, big.NewInt(2))
|
||||
contrib = contrib.Div(contrib, params.GasLimitBoundDivisor)
|
||||
|
||||
// decay = parentGasLimit / 1024 -1
|
||||
decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor)
|
||||
decay.Sub(decay, big.NewInt(1))
|
||||
|
||||
/*
|
||||
strategy: gasLimit of block-to-mine is set based on parent's
|
||||
gasUsed value. if parentGasUsed > parentGasLimit * (2/3) then we
|
||||
increase it, otherwise lower it (or leave it unchanged if it's right
|
||||
at that usage) the amount increased/decreased depends on how far away
|
||||
from parentGasLimit * (2/3) parentGasUsed is.
|
||||
*/
|
||||
gl := new(big.Int).Sub(parent.GasLimit(), decay)
|
||||
gl = gl.Add(gl, contrib)
|
||||
gl = gl.Add(gl, big.NewInt(1))
|
||||
gl.Set(common.BigMax(gl, params.MinGasLimit))
|
||||
|
||||
// however, if we're now below the target (GenesisGasLimit) we increase the
|
||||
// limit as much as we can (parentGasLimit / 1024 -1)
|
||||
if gl.Cmp(params.GenesisGasLimit) < 0 {
|
||||
gl.Add(parent.GasLimit(), decay)
|
||||
gl.Set(common.BigMin(gl, params.GenesisGasLimit))
|
||||
|
@ -1,77 +0,0 @@
|
||||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package core
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
type diffTest struct {
|
||||
ParentTimestamp uint64
|
||||
ParentDifficulty *big.Int
|
||||
CurrentTimestamp uint64
|
||||
CurrentBlocknumber *big.Int
|
||||
CurrentDifficulty *big.Int
|
||||
}
|
||||
|
||||
func (d *diffTest) UnmarshalJSON(b []byte) (err error) {
|
||||
var ext struct {
|
||||
ParentTimestamp string
|
||||
ParentDifficulty string
|
||||
CurrentTimestamp string
|
||||
CurrentBlocknumber string
|
||||
CurrentDifficulty string
|
||||
}
|
||||
if err := json.Unmarshal(b, &ext); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.ParentTimestamp = common.String2Big(ext.ParentTimestamp).Uint64()
|
||||
d.ParentDifficulty = common.String2Big(ext.ParentDifficulty)
|
||||
d.CurrentTimestamp = common.String2Big(ext.CurrentTimestamp).Uint64()
|
||||
d.CurrentBlocknumber = common.String2Big(ext.CurrentBlocknumber)
|
||||
d.CurrentDifficulty = common.String2Big(ext.CurrentDifficulty)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestDifficulty(t *testing.T) {
|
||||
file, err := os.Open("../tests/files/BasicTests/difficulty.json")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
tests := make(map[string]diffTest)
|
||||
err = json.NewDecoder(file).Decode(&tests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
number := new(big.Int).Sub(test.CurrentBlocknumber, big.NewInt(1))
|
||||
diff := CalcDifficulty(test.CurrentTimestamp, test.ParentTimestamp, number, test.ParentDifficulty)
|
||||
if diff.Cmp(test.CurrentDifficulty) != 0 {
|
||||
t.Error(name, "failed. Expected", test.CurrentDifficulty, "and calculated", diff)
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -25,10 +25,9 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
BlockNumberErr = errors.New("block number invalid")
|
||||
BlockFutureErr = errors.New("block time is in the future")
|
||||
BlockTSTooBigErr = errors.New("block time too big")
|
||||
BlockEqualTSErr = errors.New("block time stamp equal to previous")
|
||||
BlockNumberErr = errors.New("block number invalid")
|
||||
BlockFutureErr = errors.New("block time is in the future")
|
||||
BlockEqualTSErr = errors.New("block time stamp equal to previous")
|
||||
)
|
||||
|
||||
// Parent error. In case a parent is unknown this error will be thrown
|
||||
|
@ -73,7 +73,7 @@ func WriteGenesisBlock(stateDb, blockDb common.Database, reader io.Reader) (*typ
|
||||
difficulty := common.String2Big(genesis.Difficulty)
|
||||
block := types.NewBlock(&types.Header{
|
||||
Nonce: types.EncodeNonce(common.String2Big(genesis.Nonce).Uint64()),
|
||||
Time: common.String2Big(genesis.Timestamp),
|
||||
Time: common.String2Big(genesis.Timestamp).Uint64(),
|
||||
ParentHash: common.HexToHash(genesis.ParentHash),
|
||||
Extra: common.FromHex(genesis.ExtraData),
|
||||
GasLimit: common.String2Big(genesis.GasLimit),
|
||||
|
@ -82,9 +82,8 @@ type StateObject struct {
|
||||
// Mark for deletion
|
||||
// When an object is marked for deletion it will be delete from the trie
|
||||
// during the "update" phase of the state transition
|
||||
remove bool
|
||||
deleted bool
|
||||
dirty bool
|
||||
remove bool
|
||||
dirty bool
|
||||
}
|
||||
|
||||
func (self *StateObject) Reset() {
|
||||
@ -263,7 +262,6 @@ func (self *StateObject) Copy() *StateObject {
|
||||
stateObject.gasPool.Set(self.gasPool)
|
||||
stateObject.remove = self.remove
|
||||
stateObject.dirty = self.dirty
|
||||
stateObject.deleted = self.deleted
|
||||
|
||||
return stateObject
|
||||
}
|
||||
|
@ -17,7 +17,6 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
@ -118,106 +117,3 @@ func (s *StateSuite) TestSnapshot(c *checker.C) {
|
||||
|
||||
c.Assert(data1, checker.DeepEquals, res)
|
||||
}
|
||||
|
||||
// use testing instead of checker because checker does not support
|
||||
// printing/logging in tests (-check.vv does not work)
|
||||
func TestSnapshot2(t *testing.T) {
|
||||
db, _ := ethdb.NewMemDatabase()
|
||||
state := New(common.Hash{}, db)
|
||||
|
||||
stateobjaddr0 := toAddr([]byte("so0"))
|
||||
stateobjaddr1 := toAddr([]byte("so1"))
|
||||
var storageaddr common.Hash
|
||||
|
||||
data0 := common.BytesToHash([]byte{17})
|
||||
data1 := common.BytesToHash([]byte{18})
|
||||
|
||||
state.SetState(stateobjaddr0, storageaddr, data0)
|
||||
state.SetState(stateobjaddr1, storageaddr, data1)
|
||||
|
||||
// db, trie are already non-empty values
|
||||
so0 := state.GetStateObject(stateobjaddr0)
|
||||
so0.balance = big.NewInt(42)
|
||||
so0.nonce = 43
|
||||
so0.gasPool = big.NewInt(44)
|
||||
so0.code = []byte{'c', 'a', 'f', 'e'}
|
||||
so0.codeHash = so0.CodeHash()
|
||||
so0.remove = true
|
||||
so0.deleted = false
|
||||
so0.dirty = false
|
||||
state.SetStateObject(so0)
|
||||
|
||||
// and one with deleted == true
|
||||
so1 := state.GetStateObject(stateobjaddr1)
|
||||
so1.balance = big.NewInt(52)
|
||||
so1.nonce = 53
|
||||
so1.gasPool = big.NewInt(54)
|
||||
so1.code = []byte{'c', 'a', 'f', 'e', '2'}
|
||||
so1.codeHash = so1.CodeHash()
|
||||
so1.remove = true
|
||||
so1.deleted = true
|
||||
so1.dirty = true
|
||||
state.SetStateObject(so1)
|
||||
|
||||
so1 = state.GetStateObject(stateobjaddr1)
|
||||
if so1 != nil {
|
||||
t.Fatalf("deleted object not nil when getting")
|
||||
}
|
||||
|
||||
snapshot := state.Copy()
|
||||
state.Set(snapshot)
|
||||
|
||||
so0Restored := state.GetStateObject(stateobjaddr0)
|
||||
so1Restored := state.GetStateObject(stateobjaddr1)
|
||||
// non-deleted is equal (restored)
|
||||
compareStateObjects(so0Restored, so0, t)
|
||||
// deleted should be nil, both before and after restore of state copy
|
||||
if so1Restored != nil {
|
||||
t.Fatalf("deleted object not nil after restoring snapshot")
|
||||
}
|
||||
}
|
||||
|
||||
func compareStateObjects(so0, so1 *StateObject, t *testing.T) {
|
||||
if so0.address != so1.address {
|
||||
t.Fatalf("Address mismatch: have %v, want %v", so0.address, so1.address)
|
||||
}
|
||||
if so0.balance.Cmp(so1.balance) != 0 {
|
||||
t.Fatalf("Balance mismatch: have %v, want %v", so0.balance, so1.balance)
|
||||
}
|
||||
if so0.nonce != so1.nonce {
|
||||
t.Fatalf("Nonce mismatch: have %v, want %v", so0.nonce, so1.nonce)
|
||||
}
|
||||
if !bytes.Equal(so0.codeHash, so1.codeHash) {
|
||||
t.Fatalf("CodeHash mismatch: have %v, want %v", so0.codeHash, so1.codeHash)
|
||||
}
|
||||
if !bytes.Equal(so0.code, so1.code) {
|
||||
t.Fatalf("Code mismatch: have %v, want %v", so0.code, so1.code)
|
||||
}
|
||||
if !bytes.Equal(so0.initCode, so1.initCode) {
|
||||
t.Fatalf("InitCode mismatch: have %v, want %v", so0.initCode, so1.initCode)
|
||||
}
|
||||
|
||||
for k, v := range so1.storage {
|
||||
if so0.storage[k] != v {
|
||||
t.Fatalf("Storage key %s mismatch: have %v, want %v", k, so0.storage[k], v)
|
||||
}
|
||||
}
|
||||
for k, v := range so0.storage {
|
||||
if so1.storage[k] != v {
|
||||
t.Fatalf("Storage key %s mismatch: have %v, want none.", k, v)
|
||||
}
|
||||
}
|
||||
|
||||
if so0.gasPool.Cmp(so1.gasPool) != 0 {
|
||||
t.Fatalf("GasPool mismatch: have %v, want %v", so0.gasPool, so1.gasPool)
|
||||
}
|
||||
if so0.remove != so1.remove {
|
||||
t.Fatalf("Remove mismatch: have %v, want %v", so0.remove, so1.remove)
|
||||
}
|
||||
if so0.deleted != so1.deleted {
|
||||
t.Fatalf("Deleted mismatch: have %v, want %v", so0.deleted, so1.deleted)
|
||||
}
|
||||
if so0.dirty != so1.dirty {
|
||||
t.Fatalf("Dirty mismatch: have %v, want %v", so0.dirty, so1.dirty)
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,6 @@ type StateDB struct {
|
||||
thash, bhash common.Hash
|
||||
txIndex int
|
||||
logs map[common.Hash]Logs
|
||||
logSize uint
|
||||
}
|
||||
|
||||
// Create a new state from a given trie
|
||||
@ -67,9 +66,7 @@ func (self *StateDB) AddLog(log *Log) {
|
||||
log.TxHash = self.thash
|
||||
log.BlockHash = self.bhash
|
||||
log.TxIndex = uint(self.txIndex)
|
||||
log.Index = self.logSize
|
||||
self.logs[self.thash] = append(self.logs[self.thash], log)
|
||||
self.logSize++
|
||||
}
|
||||
|
||||
func (self *StateDB) GetLogs(hash common.Hash) Logs {
|
||||
@ -203,20 +200,18 @@ func (self *StateDB) UpdateStateObject(stateObject *StateObject) {
|
||||
|
||||
// Delete the given state object and delete it from the state trie
|
||||
func (self *StateDB) DeleteStateObject(stateObject *StateObject) {
|
||||
stateObject.deleted = true
|
||||
|
||||
addr := stateObject.Address()
|
||||
self.trie.Delete(addr[:])
|
||||
|
||||
//delete(self.stateObjects, addr.Str())
|
||||
}
|
||||
|
||||
// Retrieve a state object given my the address. Nil if not found
|
||||
func (self *StateDB) GetStateObject(addr common.Address) (stateObject *StateObject) {
|
||||
stateObject = self.stateObjects[addr.Str()]
|
||||
if stateObject != nil {
|
||||
if stateObject.deleted {
|
||||
stateObject = nil
|
||||
}
|
||||
func (self *StateDB) GetStateObject(addr common.Address) *StateObject {
|
||||
//addr = common.Address(addr)
|
||||
|
||||
stateObject := self.stateObjects[addr.Str()]
|
||||
if stateObject != nil {
|
||||
return stateObject
|
||||
}
|
||||
|
||||
@ -238,7 +233,7 @@ func (self *StateDB) SetStateObject(object *StateObject) {
|
||||
// Retrieve a state object or create a new state object if nil
|
||||
func (self *StateDB) GetOrNewStateObject(addr common.Address) *StateObject {
|
||||
stateObject := self.GetStateObject(addr)
|
||||
if stateObject == nil || stateObject.deleted {
|
||||
if stateObject == nil {
|
||||
stateObject = self.CreateAccount(addr)
|
||||
}
|
||||
|
||||
@ -293,7 +288,6 @@ func (self *StateDB) Copy() *StateDB {
|
||||
state.logs[hash] = make(Logs, len(logs))
|
||||
copy(state.logs[hash], logs)
|
||||
}
|
||||
state.logSize = self.logSize
|
||||
|
||||
return state
|
||||
}
|
||||
@ -304,7 +298,6 @@ func (self *StateDB) Set(state *StateDB) {
|
||||
|
||||
self.refund = state.refund
|
||||
self.logs = state.logs
|
||||
self.logSize = state.logSize
|
||||
}
|
||||
|
||||
func (s *StateDB) Root() common.Hash {
|
||||
|
@ -45,7 +45,7 @@ import (
|
||||
* 6) Derive new state root
|
||||
*/
|
||||
type StateTransition struct {
|
||||
gp GasPool
|
||||
coinbase common.Address
|
||||
msg Message
|
||||
gas, gasPrice *big.Int
|
||||
initialGas *big.Int
|
||||
@ -53,6 +53,8 @@ type StateTransition struct {
|
||||
data []byte
|
||||
state *state.StateDB
|
||||
|
||||
cb, rec, sen *state.StateObject
|
||||
|
||||
env vm.Environment
|
||||
}
|
||||
|
||||
@ -94,13 +96,13 @@ func IntrinsicGas(data []byte) *big.Int {
|
||||
return igas
|
||||
}
|
||||
|
||||
func ApplyMessage(env vm.Environment, msg Message, gp GasPool) ([]byte, *big.Int, error) {
|
||||
return NewStateTransition(env, msg, gp).transitionState()
|
||||
func ApplyMessage(env vm.Environment, msg Message, coinbase *state.StateObject) ([]byte, *big.Int, error) {
|
||||
return NewStateTransition(env, msg, coinbase).transitionState()
|
||||
}
|
||||
|
||||
func NewStateTransition(env vm.Environment, msg Message, gp GasPool) *StateTransition {
|
||||
func NewStateTransition(env vm.Environment, msg Message, coinbase *state.StateObject) *StateTransition {
|
||||
return &StateTransition{
|
||||
gp: gp,
|
||||
coinbase: coinbase.Address(),
|
||||
env: env,
|
||||
msg: msg,
|
||||
gas: new(big.Int),
|
||||
@ -109,9 +111,13 @@ func NewStateTransition(env vm.Environment, msg Message, gp GasPool) *StateTrans
|
||||
value: msg.Value(),
|
||||
data: msg.Data(),
|
||||
state: env.State(),
|
||||
cb: coinbase,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *StateTransition) Coinbase() *state.StateObject {
|
||||
return self.state.GetOrNewStateObject(self.coinbase)
|
||||
}
|
||||
func (self *StateTransition) From() (*state.StateObject, error) {
|
||||
f, err := self.msg.From()
|
||||
if err != nil {
|
||||
@ -154,7 +160,7 @@ func (self *StateTransition) BuyGas() error {
|
||||
if sender.Balance().Cmp(mgval) < 0 {
|
||||
return fmt.Errorf("insufficient ETH for gas (%x). Req %v, has %v", sender.Address().Bytes()[:4], mgval, sender.Balance())
|
||||
}
|
||||
if err = self.gp.SubGas(mgas, self.gasPrice); err != nil {
|
||||
if err = self.Coinbase().SubGas(mgas, self.gasPrice); err != nil {
|
||||
return err
|
||||
}
|
||||
self.AddGas(mgas)
|
||||
@ -235,12 +241,13 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er
|
||||
}
|
||||
|
||||
self.refundGas()
|
||||
self.state.AddBalance(self.env.Coinbase(), new(big.Int).Mul(self.gasUsed(), self.gasPrice))
|
||||
self.state.AddBalance(self.coinbase, new(big.Int).Mul(self.gasUsed(), self.gasPrice))
|
||||
|
||||
return ret, self.gasUsed(), err
|
||||
}
|
||||
|
||||
func (self *StateTransition) refundGas() {
|
||||
coinbase := self.Coinbase()
|
||||
sender, _ := self.From() // err already checked
|
||||
// Return remaining gas
|
||||
remaining := new(big.Int).Mul(self.gas, self.gasPrice)
|
||||
@ -251,7 +258,7 @@ func (self *StateTransition) refundGas() {
|
||||
self.gas.Add(self.gas, refund)
|
||||
self.state.AddBalance(sender.Address(), refund.Mul(refund, self.gasPrice))
|
||||
|
||||
self.gp.AddGas(self.gas, self.gasPrice)
|
||||
coinbase.AddGas(self.gas, self.gasPrice)
|
||||
}
|
||||
|
||||
func (self *StateTransition) gasUsed() *big.Int {
|
||||
|
@ -135,7 +135,7 @@ func (pool *TxPool) resetState() {
|
||||
func (pool *TxPool) Stop() {
|
||||
close(pool.quit)
|
||||
pool.events.Unsubscribe()
|
||||
glog.V(logger.Info).Infoln("Transaction pool stopped")
|
||||
glog.V(logger.Info).Infoln("TX Pool stopped")
|
||||
}
|
||||
|
||||
func (pool *TxPool) State() *state.ManagedState {
|
||||
@ -356,12 +356,11 @@ func (self *TxPool) RemoveTransactions(txs types.Transactions) {
|
||||
self.mu.Lock()
|
||||
defer self.mu.Unlock()
|
||||
for _, tx := range txs {
|
||||
self.RemoveTx(tx.Hash())
|
||||
self.removeTx(tx.Hash())
|
||||
}
|
||||
}
|
||||
|
||||
// RemoveTx removes the transaction with the given hash from the pool.
|
||||
func (pool *TxPool) RemoveTx(hash common.Hash) {
|
||||
func (pool *TxPool) removeTx(hash common.Hash) {
|
||||
// delete from pending pool
|
||||
delete(pool.pending, hash)
|
||||
// delete from queue
|
||||
|
@ -130,7 +130,7 @@ func TestRemoveTx(t *testing.T) {
|
||||
t.Error("expected txs to be 1, got", len(pool.pending))
|
||||
}
|
||||
|
||||
pool.RemoveTx(tx.Hash())
|
||||
pool.removeTx(tx.Hash())
|
||||
|
||||
if len(pool.queue) > 0 {
|
||||
t.Error("expected queue to be 0, got", len(pool.queue))
|
||||
|
@ -19,11 +19,9 @@ package core
|
||||
import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"github.com/syndtr/goleveldb/leveldb"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -33,21 +31,13 @@ var (
|
||||
|
||||
// PutTransactions stores the transactions in the given database
|
||||
func PutTransactions(db common.Database, block *types.Block, txs types.Transactions) {
|
||||
batch := new(leveldb.Batch)
|
||||
_, batchWrite := db.(*ethdb.LDBDatabase)
|
||||
|
||||
for i, tx := range block.Transactions() {
|
||||
rlpEnc, err := rlp.EncodeToBytes(tx)
|
||||
if err != nil {
|
||||
glog.V(logger.Debug).Infoln("Failed encoding tx", err)
|
||||
return
|
||||
}
|
||||
|
||||
if batchWrite {
|
||||
batch.Put(tx.Hash().Bytes(), rlpEnc)
|
||||
} else {
|
||||
db.Put(tx.Hash().Bytes(), rlpEnc)
|
||||
}
|
||||
db.Put(tx.Hash().Bytes(), rlpEnc)
|
||||
|
||||
var txExtra struct {
|
||||
BlockHash common.Hash
|
||||
@ -62,44 +52,20 @@ func PutTransactions(db common.Database, block *types.Block, txs types.Transacti
|
||||
glog.V(logger.Debug).Infoln("Failed encoding tx meta data", err)
|
||||
return
|
||||
}
|
||||
|
||||
if batchWrite {
|
||||
batch.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta)
|
||||
} else {
|
||||
db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta)
|
||||
}
|
||||
}
|
||||
|
||||
if db, ok := db.(*ethdb.LDBDatabase); ok {
|
||||
if err := db.LDB().Write(batch, nil); err != nil {
|
||||
glog.V(logger.Error).Infoln("db write err:", err)
|
||||
}
|
||||
db.Put(append(tx.Hash().Bytes(), 0x0001), rlpMeta)
|
||||
}
|
||||
}
|
||||
|
||||
// PutReceipts stores the receipts in the current database
|
||||
func PutReceipts(db common.Database, receipts types.Receipts) error {
|
||||
batch := new(leveldb.Batch)
|
||||
_, batchWrite := db.(*ethdb.LDBDatabase)
|
||||
|
||||
for _, receipt := range receipts {
|
||||
storageReceipt := (*types.ReceiptForStorage)(receipt)
|
||||
bytes, err := rlp.EncodeToBytes(storageReceipt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if batchWrite {
|
||||
batch.Put(append(receiptsPre, receipt.TxHash[:]...), bytes)
|
||||
} else {
|
||||
err = db.Put(append(receiptsPre, receipt.TxHash[:]...), bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
if db, ok := db.(*ethdb.LDBDatabase); ok {
|
||||
if err := db.LDB().Write(batch, nil); err != nil {
|
||||
err = db.Put(append(receiptsPre, receipt.TxHash[:]...), bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ type Header struct {
|
||||
Number *big.Int // The block number
|
||||
GasLimit *big.Int // Gas limit
|
||||
GasUsed *big.Int // Gas used
|
||||
Time *big.Int // Creation time
|
||||
Time uint64 // Creation time
|
||||
Extra []byte // Extra data
|
||||
MixDigest common.Hash // for quick difficulty verification
|
||||
Nonce BlockNonce
|
||||
@ -94,7 +94,7 @@ func (h *Header) UnmarshalJSON(data []byte) error {
|
||||
Coinbase string
|
||||
Difficulty string
|
||||
GasLimit string
|
||||
Time *big.Int
|
||||
Time uint64
|
||||
Extra string
|
||||
}
|
||||
dec := json.NewDecoder(bytes.NewReader(data))
|
||||
@ -210,9 +210,6 @@ func NewBlockWithHeader(header *Header) *Block {
|
||||
|
||||
func copyHeader(h *Header) *Header {
|
||||
cpy := *h
|
||||
if cpy.Time = new(big.Int); h.Time != nil {
|
||||
cpy.Time.Set(h.Time)
|
||||
}
|
||||
if cpy.Difficulty = new(big.Int); h.Difficulty != nil {
|
||||
cpy.Difficulty.Set(h.Difficulty)
|
||||
}
|
||||
@ -260,7 +257,7 @@ func (b *Block) DecodeRLP(s *rlp.Stream) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Block) EncodeRLP(w io.Writer) error {
|
||||
func (b Block) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, extblock{
|
||||
Header: b.header,
|
||||
Txs: b.transactions,
|
||||
@ -277,7 +274,7 @@ func (b *StorageBlock) DecodeRLP(s *rlp.Stream) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *StorageBlock) EncodeRLP(w io.Writer) error {
|
||||
func (b StorageBlock) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, storageblock{
|
||||
Header: b.header,
|
||||
Txs: b.transactions,
|
||||
@ -304,13 +301,13 @@ func (b *Block) Number() *big.Int { return new(big.Int).Set(b.header.Number)
|
||||
func (b *Block) GasLimit() *big.Int { return new(big.Int).Set(b.header.GasLimit) }
|
||||
func (b *Block) GasUsed() *big.Int { return new(big.Int).Set(b.header.GasUsed) }
|
||||
func (b *Block) Difficulty() *big.Int { return new(big.Int).Set(b.header.Difficulty) }
|
||||
func (b *Block) Time() *big.Int { return new(big.Int).Set(b.header.Time) }
|
||||
|
||||
func (b *Block) NumberU64() uint64 { return b.header.Number.Uint64() }
|
||||
func (b *Block) MixDigest() common.Hash { return b.header.MixDigest }
|
||||
func (b *Block) Nonce() uint64 { return binary.BigEndian.Uint64(b.header.Nonce[:]) }
|
||||
func (b *Block) Bloom() Bloom { return b.header.Bloom }
|
||||
func (b *Block) Coinbase() common.Address { return b.header.Coinbase }
|
||||
func (b *Block) Time() uint64 { return b.header.Time }
|
||||
func (b *Block) Root() common.Hash { return b.header.Root }
|
||||
func (b *Block) ParentHash() common.Hash { return b.header.ParentHash }
|
||||
func (b *Block) TxHash() common.Hash { return b.header.TxHash }
|
||||
|
@ -47,7 +47,7 @@ func TestBlockEncoding(t *testing.T) {
|
||||
check("Root", block.Root(), common.HexToHash("ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017"))
|
||||
check("Hash", block.Hash(), common.HexToHash("0a5843ac1cb04865017cb35a57b50b07084e5fcee39b5acadade33149f4fff9e"))
|
||||
check("Nonce", block.Nonce(), uint64(0xa13a5a8c8f2bb1c4))
|
||||
check("Time", block.Time(), big.NewInt(1426516743))
|
||||
check("Time", block.Time(), uint64(1426516743))
|
||||
check("Size", block.Size(), common.StorageSize(len(blockEnc)))
|
||||
|
||||
tx1 := NewTransaction(0, common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"), big.NewInt(10), big.NewInt(50000), big.NewInt(10), nil)
|
||||
|
@ -97,6 +97,15 @@ func NewTransaction(nonce uint64, to common.Address, amount, gasLimit, gasPrice
|
||||
return &Transaction{data: d}
|
||||
}
|
||||
|
||||
func NewTransactionFromBytes(data []byte) *Transaction {
|
||||
// TODO: remove this function if possible. callers would
|
||||
// much better off decoding into transaction directly.
|
||||
// it's not that hard.
|
||||
tx := new(Transaction)
|
||||
rlp.DecodeBytes(data, tx)
|
||||
return tx
|
||||
}
|
||||
|
||||
func (tx *Transaction) EncodeRLP(w io.Writer) error {
|
||||
return rlp.Encode(w, &tx.data)
|
||||
}
|
||||
@ -289,22 +298,3 @@ type TxByNonce struct{ Transactions }
|
||||
func (s TxByNonce) Less(i, j int) bool {
|
||||
return s.Transactions[i].data.AccountNonce < s.Transactions[j].data.AccountNonce
|
||||
}
|
||||
|
||||
type TxByPrice struct{ Transactions }
|
||||
|
||||
func (s TxByPrice) Less(i, j int) bool {
|
||||
return s.Transactions[i].data.Price.Cmp(s.Transactions[j].data.Price) > 0
|
||||
}
|
||||
|
||||
type TxByPriceAndNonce struct{ Transactions }
|
||||
|
||||
func (s TxByPriceAndNonce) Less(i, j int) bool {
|
||||
// we can ignore the error here. Sorting shouldn't care about validness
|
||||
ifrom, _ := s.Transactions[i].From()
|
||||
jfrom, _ := s.Transactions[j].From()
|
||||
// favour nonce if they are from the same recipient
|
||||
if ifrom == jfrom {
|
||||
return s.Transactions[i].data.AccountNonce < s.Transactions[j].data.AccountNonce
|
||||
}
|
||||
return s.Transactions[i].data.Price.Cmp(s.Transactions[j].data.Price) > 0
|
||||
}
|
||||
|
@ -31,11 +31,9 @@ type Environment interface {
|
||||
|
||||
Origin() common.Address
|
||||
BlockNumber() *big.Int
|
||||
// The n'th hash ago from this block number
|
||||
GetHash(uint64) common.Hash
|
||||
// The handler's address
|
||||
GetHash(n uint64) common.Hash
|
||||
Coinbase() common.Address
|
||||
Time() *big.Int
|
||||
Time() uint64
|
||||
Difficulty() *big.Int
|
||||
GasLimit() *big.Int
|
||||
Transfer(from, to Account, amount *big.Int) error
|
||||
|
@ -461,7 +461,7 @@ func (self *Vm) Run(context *Context, input []byte) (ret []byte, err error) {
|
||||
case TIMESTAMP:
|
||||
time := self.env.Time()
|
||||
|
||||
stack.push(new(big.Int).Set(time))
|
||||
stack.push(new(big.Int).SetUint64(time))
|
||||
|
||||
case NUMBER:
|
||||
number := self.env.BlockNumber()
|
||||
|
@ -49,7 +49,7 @@ func NewEnv(state *state.StateDB, chain *ChainManager, msg Message, header *type
|
||||
func (self *VMEnv) Origin() common.Address { f, _ := self.msg.From(); return f }
|
||||
func (self *VMEnv) BlockNumber() *big.Int { return self.header.Number }
|
||||
func (self *VMEnv) Coinbase() common.Address { return self.header.Coinbase }
|
||||
func (self *VMEnv) Time() *big.Int { return self.header.Time }
|
||||
func (self *VMEnv) Time() uint64 { return self.header.Time }
|
||||
func (self *VMEnv) Difficulty() *big.Int { return self.header.Difficulty }
|
||||
func (self *VMEnv) GasLimit() *big.Int { return self.header.GasLimit }
|
||||
func (self *VMEnv) Value() *big.Int { return self.msg.Value() }
|
||||
@ -59,10 +59,8 @@ func (self *VMEnv) SetDepth(i int) { self.depth = i }
|
||||
func (self *VMEnv) VmType() vm.Type { return self.typ }
|
||||
func (self *VMEnv) SetVmType(t vm.Type) { self.typ = t }
|
||||
func (self *VMEnv) GetHash(n uint64) common.Hash {
|
||||
for block := self.chain.GetBlock(self.header.ParentHash); block != nil; block = self.chain.GetBlock(block.ParentHash()) {
|
||||
if block.NumberU64() == n {
|
||||
return block.Hash()
|
||||
}
|
||||
if block := self.chain.GetBlockByNumber(n); block != nil {
|
||||
return block.Hash()
|
||||
}
|
||||
|
||||
return common.Hash{}
|
||||
|
@ -60,14 +60,7 @@ type BitCurve struct {
|
||||
}
|
||||
|
||||
func (BitCurve *BitCurve) Params() *elliptic.CurveParams {
|
||||
return &elliptic.CurveParams{
|
||||
P: BitCurve.P,
|
||||
N: BitCurve.N,
|
||||
B: BitCurve.B,
|
||||
Gx: BitCurve.Gx,
|
||||
Gy: BitCurve.Gy,
|
||||
BitSize: BitCurve.BitSize,
|
||||
}
|
||||
return &elliptic.CurveParams{BitCurve.P, BitCurve.N, BitCurve.B, BitCurve.Gx, BitCurve.Gy, BitCurve.BitSize}
|
||||
}
|
||||
|
||||
// IsOnBitCurve returns true if the given (x,y) lies on the BitCurve.
|
||||
|
@ -81,9 +81,11 @@ func doScheme(base, v []int) asn1.ObjectIdentifier {
|
||||
type secgNamedCurve asn1.ObjectIdentifier
|
||||
|
||||
var (
|
||||
secgNamedCurveP224 = secgNamedCurve{1, 3, 132, 0, 33}
|
||||
secgNamedCurveP256 = secgNamedCurve{1, 2, 840, 10045, 3, 1, 7}
|
||||
secgNamedCurveP384 = secgNamedCurve{1, 3, 132, 0, 34}
|
||||
secgNamedCurveP521 = secgNamedCurve{1, 3, 132, 0, 35}
|
||||
rawCurveP224 = []byte{6, 5, 4, 3, 1, 2, 9, 4, 0, 3, 3}
|
||||
rawCurveP256 = []byte{6, 8, 4, 2, 1, 3, 4, 7, 2, 2, 0, 6, 6, 1, 3, 1, 7}
|
||||
rawCurveP384 = []byte{6, 5, 4, 3, 1, 2, 9, 4, 0, 3, 4}
|
||||
rawCurveP521 = []byte{6, 5, 4, 3, 1, 2, 9, 4, 0, 3, 5}
|
||||
@ -91,6 +93,8 @@ var (
|
||||
|
||||
func rawCurve(curve elliptic.Curve) []byte {
|
||||
switch curve {
|
||||
case elliptic.P224():
|
||||
return rawCurveP224
|
||||
case elliptic.P256():
|
||||
return rawCurveP256
|
||||
case elliptic.P384():
|
||||
@ -116,6 +120,8 @@ func (curve secgNamedCurve) Equal(curve2 secgNamedCurve) bool {
|
||||
|
||||
func namedCurveFromOID(curve secgNamedCurve) elliptic.Curve {
|
||||
switch {
|
||||
case curve.Equal(secgNamedCurveP224):
|
||||
return elliptic.P224()
|
||||
case curve.Equal(secgNamedCurveP256):
|
||||
return elliptic.P256()
|
||||
case curve.Equal(secgNamedCurveP384):
|
||||
@ -128,6 +134,8 @@ func namedCurveFromOID(curve secgNamedCurve) elliptic.Curve {
|
||||
|
||||
func oidFromNamedCurve(curve elliptic.Curve) (secgNamedCurve, bool) {
|
||||
switch curve {
|
||||
case elliptic.P224():
|
||||
return secgNamedCurveP224, true
|
||||
case elliptic.P256():
|
||||
return secgNamedCurveP256, true
|
||||
case elliptic.P384():
|
||||
@ -240,7 +248,7 @@ var idEcPublicKeySupplemented = doScheme(idPublicKeyType, []int{0})
|
||||
|
||||
func curveToRaw(curve elliptic.Curve) (rv asn1.RawValue, ok bool) {
|
||||
switch curve {
|
||||
case elliptic.P256(), elliptic.P384(), elliptic.P521():
|
||||
case elliptic.P224(), elliptic.P256(), elliptic.P384(), elliptic.P521():
|
||||
raw := rawCurve(curve)
|
||||
return asn1.RawValue{
|
||||
Tag: 30,
|
||||
|
@ -407,6 +407,11 @@ type testCase struct {
|
||||
}
|
||||
|
||||
var testCases = []testCase{
|
||||
testCase{
|
||||
Curve: elliptic.P224(),
|
||||
Name: "P224",
|
||||
Expected: false,
|
||||
},
|
||||
testCase{
|
||||
Curve: elliptic.P256(),
|
||||
Name: "P256",
|
||||
|
@ -147,6 +147,7 @@ func (ks keyStorePassphrase) DeleteKey(keyAddr common.Address, auth string) (err
|
||||
}
|
||||
|
||||
func decryptKeyFromFile(keysDirPath string, keyAddr common.Address, auth string) (keyBytes []byte, keyId []byte, err error) {
|
||||
fmt.Printf("%v\n", keyAddr.Hex())
|
||||
m := make(map[string]interface{})
|
||||
err = getKey(keysDirPath, keyAddr, &m)
|
||||
if err != nil {
|
||||
|
@ -21,11 +21,9 @@ package secp256k1
|
||||
/*
|
||||
#cgo CFLAGS: -I./secp256k1
|
||||
#cgo darwin CFLAGS: -I/usr/local/include
|
||||
#cgo freebsd CFLAGS: -I/usr/local/include
|
||||
#cgo linux,arm CFLAGS: -I/usr/local/arm/include
|
||||
#cgo LDFLAGS: -lgmp
|
||||
#cgo darwin LDFLAGS: -L/usr/local/lib
|
||||
#cgo freebsd LDFLAGS: -L/usr/local/lib
|
||||
#cgo linux,arm LDFLAGS: -L/usr/local/arm/lib
|
||||
#define USE_NUM_GMP
|
||||
#define USE_FIELD_10X26
|
||||
|
@ -78,11 +78,9 @@ type Config struct {
|
||||
GenesisNonce int
|
||||
GenesisFile string
|
||||
GenesisBlock *types.Block // used by block tests
|
||||
Olympic bool
|
||||
|
||||
BlockChainVersion int
|
||||
SkipBcVersionCheck bool // e.g. blockchain export
|
||||
DatabaseCache int
|
||||
|
||||
DataDir string
|
||||
LogFile string
|
||||
@ -264,7 +262,7 @@ func New(config *Config) (*Ethereum, error) {
|
||||
|
||||
newdb := config.NewDB
|
||||
if newdb == nil {
|
||||
newdb = func(path string) (common.Database, error) { return ethdb.NewLDBDatabase(path, config.DatabaseCache) }
|
||||
newdb = func(path string) (common.Database, error) { return ethdb.NewLDBDatabase(path) }
|
||||
}
|
||||
blockDb, err := newdb(filepath.Join(config.DataDir, "blockchain"))
|
||||
if err != nil {
|
||||
@ -303,14 +301,6 @@ func New(config *Config) (*Ethereum, error) {
|
||||
glog.V(logger.Info).Infof("Successfully wrote genesis block. New genesis hash = %x\n", block.Hash())
|
||||
}
|
||||
|
||||
if config.Olympic {
|
||||
_, err := core.WriteTestNetGenesisBlock(stateDb, blockDb, 42)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
glog.V(logger.Error).Infoln("Starting Olympic network")
|
||||
}
|
||||
|
||||
// This is for testing only.
|
||||
if config.GenesisBlock != nil {
|
||||
core.WriteBlock(blockDb, config.GenesisBlock)
|
||||
|
@ -28,13 +28,12 @@ import (
|
||||
"github.com/ethereum/go-ethereum/core"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/params"
|
||||
)
|
||||
|
||||
var (
|
||||
testdb, _ = ethdb.NewMemDatabase()
|
||||
genesis = core.GenesisBlockForTesting(testdb, common.Address{}, big.NewInt(0))
|
||||
unknownBlock = types.NewBlock(&types.Header{GasLimit: params.GenesisGasLimit}, nil, nil, nil)
|
||||
unknownBlock = types.NewBlock(&types.Header{}, nil, nil, nil)
|
||||
)
|
||||
|
||||
// makeChain creates a chain of n blocks starting at and including parent.
|
||||
|
@ -117,7 +117,7 @@ func NewProtocolManager(networkId int, mux *event.TypeMux, txpool txPool, pow po
|
||||
manager.downloader = downloader.New(manager.eventMux, manager.chainman.HasBlock, manager.chainman.GetBlock, manager.chainman.CurrentBlock, manager.chainman.InsertChain, manager.removePeer)
|
||||
|
||||
validator := func(block *types.Block, parent *types.Block) error {
|
||||
return core.ValidateHeader(pow, block.Header(), parent, true, false)
|
||||
return core.ValidateHeader(pow, block.Header(), parent, true)
|
||||
}
|
||||
heighter := func() uint64 {
|
||||
return manager.chainman.CurrentBlock().NumberU64()
|
||||
|
@ -17,7 +17,6 @@
|
||||
package ethdb
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@ -36,14 +35,6 @@ import (
|
||||
|
||||
var OpenFileLimit = 64
|
||||
|
||||
// cacheRatio specifies how the total alloted cache is distributed between the
|
||||
// various system databases.
|
||||
var cacheRatio = map[string]float64{
|
||||
"blockchain": 1.0 / 13.0,
|
||||
"extra": 2.0 / 13.0,
|
||||
"state": 10.0 / 13.0,
|
||||
}
|
||||
|
||||
type LDBDatabase struct {
|
||||
fn string // filename for reporting
|
||||
db *leveldb.DB // LevelDB instance
|
||||
@ -65,24 +56,14 @@ type LDBDatabase struct {
|
||||
// NewLDBDatabase returns a LevelDB wrapped object. LDBDatabase does not persist data by
|
||||
// it self but requires a background poller which syncs every X. `Flush` should be called
|
||||
// when data needs to be stored and written to disk.
|
||||
func NewLDBDatabase(file string, cache int) (*LDBDatabase, error) {
|
||||
// Calculate the cache allowance for this particular database
|
||||
cache = int(float64(cache) * cacheRatio[filepath.Base(file)])
|
||||
if cache < 16 {
|
||||
cache = 16
|
||||
}
|
||||
glog.V(logger.Info).Infof("Alloted %dMB cache to %s", cache, file)
|
||||
|
||||
// Open the db and recover any potential corruptions
|
||||
db, err := leveldb.OpenFile(file, &opt.Options{
|
||||
OpenFilesCacheCapacity: OpenFileLimit,
|
||||
BlockCacheCapacity: cache / 2 * opt.MiB,
|
||||
WriteBuffer: cache / 4 * opt.MiB, // Two of these are used internally
|
||||
})
|
||||
if _, corrupted := err.(*errors.ErrCorrupted); corrupted {
|
||||
func NewLDBDatabase(file string) (*LDBDatabase, error) {
|
||||
// Open the db
|
||||
db, err := leveldb.OpenFile(file, &opt.Options{OpenFilesCacheCapacity: OpenFileLimit})
|
||||
// check for corruption and attempt to recover
|
||||
if _, iscorrupted := err.(*errors.ErrCorrupted); iscorrupted {
|
||||
db, err = leveldb.RecoverFile(file, nil)
|
||||
}
|
||||
// (Re)check for errors and abort if opening of the db failed
|
||||
// (re) check for errors and abort if opening of the db failed
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -28,7 +28,8 @@ func newDb() *LDBDatabase {
|
||||
if common.FileExist(file) {
|
||||
os.RemoveAll(file)
|
||||
}
|
||||
db, _ := NewLDBDatabase(file, 0)
|
||||
|
||||
db, _ := NewLDBDatabase(file)
|
||||
|
||||
return db
|
||||
}
|
||||
|
@ -1,112 +0,0 @@
|
||||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Package fdtrack logs statistics about open file descriptors.
|
||||
package fdtrack
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
)
|
||||
|
||||
var (
|
||||
mutex sync.Mutex
|
||||
all = make(map[string]int)
|
||||
)
|
||||
|
||||
func Open(desc string) {
|
||||
mutex.Lock()
|
||||
all[desc] += 1
|
||||
mutex.Unlock()
|
||||
}
|
||||
|
||||
func Close(desc string) {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
if c, ok := all[desc]; ok {
|
||||
if c == 1 {
|
||||
delete(all, desc)
|
||||
} else {
|
||||
all[desc]--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func WrapListener(desc string, l net.Listener) net.Listener {
|
||||
Open(desc)
|
||||
return &wrappedListener{l, desc}
|
||||
}
|
||||
|
||||
type wrappedListener struct {
|
||||
net.Listener
|
||||
desc string
|
||||
}
|
||||
|
||||
func (w *wrappedListener) Accept() (net.Conn, error) {
|
||||
c, err := w.Listener.Accept()
|
||||
if err == nil {
|
||||
c = WrapConn(w.desc, c)
|
||||
}
|
||||
return c, err
|
||||
}
|
||||
|
||||
func (w *wrappedListener) Close() error {
|
||||
err := w.Listener.Close()
|
||||
if err == nil {
|
||||
Close(w.desc)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func WrapConn(desc string, conn net.Conn) net.Conn {
|
||||
Open(desc)
|
||||
return &wrappedConn{conn, desc}
|
||||
}
|
||||
|
||||
type wrappedConn struct {
|
||||
net.Conn
|
||||
desc string
|
||||
}
|
||||
|
||||
func (w *wrappedConn) Close() error {
|
||||
err := w.Conn.Close()
|
||||
if err == nil {
|
||||
Close(w.desc)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func Start() {
|
||||
go func() {
|
||||
for range time.Tick(15 * time.Second) {
|
||||
mutex.Lock()
|
||||
var sum, tracked = 0, []string{}
|
||||
for what, n := range all {
|
||||
sum += n
|
||||
tracked = append(tracked, fmt.Sprintf("%s:%d", what, n))
|
||||
}
|
||||
mutex.Unlock()
|
||||
used, _ := fdusage()
|
||||
sort.Strings(tracked)
|
||||
glog.Infof("fd usage %d/%d, tracked %d %v", used, fdlimit(), sum, tracked)
|
||||
}
|
||||
}()
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// +build !linux,!darwin
|
||||
|
||||
package fdtrack
|
||||
|
||||
import "errors"
|
||||
|
||||
func fdlimit() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func fdusage() (int, error) {
|
||||
return 0, errors.New("not implemented")
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// +build darwin
|
||||
|
||||
package fdtrack
|
||||
|
||||
import (
|
||||
"os"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// #cgo CFLAGS: -lproc
|
||||
// #include <libproc.h>
|
||||
// #include <stdlib.h>
|
||||
import "C"
|
||||
|
||||
func fdlimit() int {
|
||||
var nofile syscall.Rlimit
|
||||
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &nofile); err != nil {
|
||||
return 0
|
||||
}
|
||||
return int(nofile.Cur)
|
||||
}
|
||||
|
||||
func fdusage() (int, error) {
|
||||
pid := C.int(os.Getpid())
|
||||
// Query for a rough estimate on the amout of data that
|
||||
// proc_pidinfo will return.
|
||||
rlen, err := C.proc_pidinfo(pid, C.PROC_PIDLISTFDS, 0, nil, 0)
|
||||
if rlen <= 0 {
|
||||
return 0, err
|
||||
}
|
||||
// Load the list of file descriptors. We don't actually care about
|
||||
// the content, only about the size. Since the number of fds can
|
||||
// change while we're reading them, the loop enlarges the buffer
|
||||
// until proc_pidinfo says the result fitted.
|
||||
var buf unsafe.Pointer
|
||||
defer func() {
|
||||
if buf != nil {
|
||||
C.free(buf)
|
||||
}
|
||||
}()
|
||||
for buflen := rlen; ; buflen *= 2 {
|
||||
buf, err = C.reallocf(buf, C.size_t(buflen))
|
||||
if buf == nil {
|
||||
return 0, err
|
||||
}
|
||||
rlen, err = C.proc_pidinfo(pid, C.PROC_PIDLISTFDS, 0, buf, buflen)
|
||||
if rlen <= 0 {
|
||||
return 0, err
|
||||
} else if rlen == buflen {
|
||||
continue
|
||||
}
|
||||
return int(rlen / C.PROC_PIDLISTFD_SIZE), nil
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
@ -1,53 +0,0 @@
|
||||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// +build linux
|
||||
|
||||
package fdtrack
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func fdlimit() int {
|
||||
var nofile syscall.Rlimit
|
||||
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &nofile); err != nil {
|
||||
return 0
|
||||
}
|
||||
return int(nofile.Cur)
|
||||
}
|
||||
|
||||
func fdusage() (int, error) {
|
||||
f, err := os.Open("/proc/self/fd")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer f.Close()
|
||||
const batchSize = 100
|
||||
n := 0
|
||||
for {
|
||||
list, err := f.Readdirnames(batchSize)
|
||||
n += len(list)
|
||||
if err == io.EOF {
|
||||
break
|
||||
} else if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
return n, nil
|
||||
}
|
@ -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);
|
||||
|
@ -34,7 +34,6 @@ func ReadDiskStats(stats *DiskStats) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer inf.Close()
|
||||
in := bufio.NewReader(inf)
|
||||
|
||||
// Iterate over the IO counter, and extract what we need
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
"github.com/ethereum/go-ethereum/pow"
|
||||
@ -28,10 +29,10 @@ import (
|
||||
type CpuAgent struct {
|
||||
mu sync.Mutex
|
||||
|
||||
workCh chan *Work
|
||||
workCh chan *types.Block
|
||||
quit chan struct{}
|
||||
quitCurrentOp chan struct{}
|
||||
returnCh chan<- *Result
|
||||
returnCh chan<- *types.Block
|
||||
|
||||
index int
|
||||
pow pow.PoW
|
||||
@ -46,9 +47,9 @@ func NewCpuAgent(index int, pow pow.PoW) *CpuAgent {
|
||||
return miner
|
||||
}
|
||||
|
||||
func (self *CpuAgent) Work() chan<- *Work { return self.workCh }
|
||||
func (self *CpuAgent) Pow() pow.PoW { return self.pow }
|
||||
func (self *CpuAgent) SetReturnCh(ch chan<- *Result) { self.returnCh = ch }
|
||||
func (self *CpuAgent) Work() chan<- *types.Block { return self.workCh }
|
||||
func (self *CpuAgent) Pow() pow.PoW { return self.pow }
|
||||
func (self *CpuAgent) SetReturnCh(ch chan<- *types.Block) { self.returnCh = ch }
|
||||
|
||||
func (self *CpuAgent) Stop() {
|
||||
self.mu.Lock()
|
||||
@ -64,7 +65,7 @@ func (self *CpuAgent) Start() {
|
||||
self.quit = make(chan struct{})
|
||||
// creating current op ch makes sure we're not closing a nil ch
|
||||
// later on
|
||||
self.workCh = make(chan *Work, 1)
|
||||
self.workCh = make(chan *types.Block, 1)
|
||||
|
||||
go self.update()
|
||||
}
|
||||
@ -73,13 +74,13 @@ func (self *CpuAgent) update() {
|
||||
out:
|
||||
for {
|
||||
select {
|
||||
case work := <-self.workCh:
|
||||
case block := <-self.workCh:
|
||||
self.mu.Lock()
|
||||
if self.quitCurrentOp != nil {
|
||||
close(self.quitCurrentOp)
|
||||
}
|
||||
self.quitCurrentOp = make(chan struct{})
|
||||
go self.mine(work, self.quitCurrentOp)
|
||||
go self.mine(block, self.quitCurrentOp)
|
||||
self.mu.Unlock()
|
||||
case <-self.quit:
|
||||
self.mu.Lock()
|
||||
@ -105,14 +106,13 @@ done:
|
||||
}
|
||||
}
|
||||
|
||||
func (self *CpuAgent) mine(work *Work, stop <-chan struct{}) {
|
||||
func (self *CpuAgent) mine(block *types.Block, stop <-chan struct{}) {
|
||||
glog.V(logger.Debug).Infof("(re)started agent[%d]. mining...\n", self.index)
|
||||
|
||||
// Mine
|
||||
nonce, mixDigest := self.pow.Search(work.Block, stop)
|
||||
nonce, mixDigest := self.pow.Search(block, stop)
|
||||
if nonce != 0 {
|
||||
block := work.Block.WithMiningResult(nonce, common.BytesToHash(mixDigest))
|
||||
self.returnCh <- &Result{work, block}
|
||||
self.returnCh <- block.WithMiningResult(nonce, common.BytesToHash(mixDigest))
|
||||
} else {
|
||||
self.returnCh <- nil
|
||||
}
|
||||
|
@ -18,44 +18,39 @@ package miner
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/ethash"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
type RemoteAgent struct {
|
||||
mu sync.Mutex
|
||||
work *types.Block
|
||||
currentWork *types.Block
|
||||
|
||||
quit chan struct{}
|
||||
workCh chan *Work
|
||||
returnCh chan<- *Result
|
||||
|
||||
currentWork *Work
|
||||
work map[common.Hash]*Work
|
||||
workCh chan *types.Block
|
||||
returnCh chan<- *types.Block
|
||||
}
|
||||
|
||||
func NewRemoteAgent() *RemoteAgent {
|
||||
agent := &RemoteAgent{work: make(map[common.Hash]*Work)}
|
||||
agent := &RemoteAgent{}
|
||||
|
||||
return agent
|
||||
}
|
||||
|
||||
func (a *RemoteAgent) Work() chan<- *Work {
|
||||
func (a *RemoteAgent) Work() chan<- *types.Block {
|
||||
return a.workCh
|
||||
}
|
||||
|
||||
func (a *RemoteAgent) SetReturnCh(returnCh chan<- *Result) {
|
||||
func (a *RemoteAgent) SetReturnCh(returnCh chan<- *types.Block) {
|
||||
a.returnCh = returnCh
|
||||
}
|
||||
|
||||
func (a *RemoteAgent) Start() {
|
||||
a.quit = make(chan struct{})
|
||||
a.workCh = make(chan *Work, 1)
|
||||
go a.maintainLoop()
|
||||
a.workCh = make(chan *types.Block, 1)
|
||||
go a.run()
|
||||
}
|
||||
|
||||
func (a *RemoteAgent) Stop() {
|
||||
@ -65,72 +60,47 @@ func (a *RemoteAgent) Stop() {
|
||||
|
||||
func (a *RemoteAgent) GetHashRate() int64 { return 0 }
|
||||
|
||||
func (a *RemoteAgent) GetWork() [3]string {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
|
||||
var res [3]string
|
||||
|
||||
if a.currentWork != nil {
|
||||
block := a.currentWork.Block
|
||||
|
||||
res[0] = block.HashNoNonce().Hex()
|
||||
seedHash, _ := ethash.GetSeedHash(block.NumberU64())
|
||||
res[1] = common.BytesToHash(seedHash).Hex()
|
||||
// Calculate the "target" to be returned to the external miner
|
||||
n := big.NewInt(1)
|
||||
n.Lsh(n, 255)
|
||||
n.Div(n, block.Difficulty())
|
||||
n.Lsh(n, 1)
|
||||
res[2] = common.BytesToHash(n.Bytes()).Hex()
|
||||
|
||||
a.work[block.HashNoNonce()] = a.currentWork
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// Returns true or false, but does not indicate if the PoW was correct
|
||||
func (a *RemoteAgent) SubmitWork(nonce uint64, mixDigest, hash common.Hash) bool {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
|
||||
// Make sure the work submitted is present
|
||||
if a.work[hash] != nil {
|
||||
block := a.work[hash].Block.WithMiningResult(nonce, mixDigest)
|
||||
a.returnCh <- &Result{a.work[hash], block}
|
||||
|
||||
delete(a.work, hash)
|
||||
|
||||
return true
|
||||
} else {
|
||||
glog.V(logger.Info).Infof("Work was submitted for %x but no pending work found\n", hash)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *RemoteAgent) maintainLoop() {
|
||||
ticker := time.Tick(5 * time.Second)
|
||||
|
||||
func (a *RemoteAgent) run() {
|
||||
out:
|
||||
for {
|
||||
select {
|
||||
case <-a.quit:
|
||||
break out
|
||||
case work := <-a.workCh:
|
||||
a.mu.Lock()
|
||||
a.currentWork = work
|
||||
a.mu.Unlock()
|
||||
case <-ticker:
|
||||
// cleanup
|
||||
a.mu.Lock()
|
||||
for hash, work := range a.work {
|
||||
if time.Since(work.createdAt) > 7*(12*time.Second) {
|
||||
delete(a.work, hash)
|
||||
}
|
||||
}
|
||||
a.mu.Unlock()
|
||||
a.work = work
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *RemoteAgent) GetWork() [3]string {
|
||||
var res [3]string
|
||||
|
||||
if a.work != nil {
|
||||
a.currentWork = a.work
|
||||
|
||||
res[0] = a.work.HashNoNonce().Hex()
|
||||
seedHash, _ := ethash.GetSeedHash(a.currentWork.NumberU64())
|
||||
res[1] = common.BytesToHash(seedHash).Hex()
|
||||
// Calculate the "target" to be returned to the external miner
|
||||
n := big.NewInt(1)
|
||||
n.Lsh(n, 255)
|
||||
n.Div(n, a.work.Difficulty())
|
||||
n.Lsh(n, 1)
|
||||
res[2] = common.BytesToHash(n.Bytes()).Hex()
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (a *RemoteAgent) SubmitWork(nonce uint64, mixDigest, seedHash common.Hash) bool {
|
||||
// Return true or false, but does not indicate if the PoW was correct
|
||||
|
||||
// Make sure the external miner was working on the right hash
|
||||
if a.currentWork != nil && a.work != nil {
|
||||
a.returnCh <- a.currentWork.WithMiningResult(nonce, mixDigest)
|
||||
//a.returnCh <- Work{a.currentWork.Number().Uint64(), nonce, mixDigest.Bytes(), seedHash.Bytes()}
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
246
miner/worker.go
246
miner/worker.go
@ -38,20 +38,25 @@ import (
|
||||
|
||||
var jsonlogger = logger.NewJsonLogger()
|
||||
|
||||
const (
|
||||
resultQueueSize = 10
|
||||
miningLogAtDepth = 5
|
||||
)
|
||||
// Work holds the current work
|
||||
type Work struct {
|
||||
Number uint64
|
||||
Nonce uint64
|
||||
MixDigest []byte
|
||||
SeedHash []byte
|
||||
}
|
||||
|
||||
// Agent can register themself with the worker
|
||||
type Agent interface {
|
||||
Work() chan<- *Work
|
||||
SetReturnCh(chan<- *Result)
|
||||
Work() chan<- *types.Block
|
||||
SetReturnCh(chan<- *types.Block)
|
||||
Stop()
|
||||
Start()
|
||||
GetHashRate() int64
|
||||
}
|
||||
|
||||
const miningLogAtDepth = 5
|
||||
|
||||
type uint64RingBuffer struct {
|
||||
ints []uint64 //array of all integers in buffer
|
||||
next int //where is the next insertion? assert 0 <= next < len(ints)
|
||||
@ -59,7 +64,7 @@ type uint64RingBuffer struct {
|
||||
|
||||
// environment is the workers current environment and holds
|
||||
// all of the current state information
|
||||
type Work struct {
|
||||
type environment struct {
|
||||
state *state.StateDB // apply state changes here
|
||||
coinbase *state.StateObject // the miner's account
|
||||
ancestors *set.Set // ancestor set (used for checking uncle parent validity)
|
||||
@ -73,18 +78,11 @@ type Work struct {
|
||||
lowGasTxs types.Transactions
|
||||
localMinedBlocks *uint64RingBuffer // the most recent block numbers that were mined locally (used to check block inclusion)
|
||||
|
||||
Block *types.Block // the new block
|
||||
block *types.Block // the new block
|
||||
|
||||
header *types.Header
|
||||
txs []*types.Transaction
|
||||
receipts []*types.Receipt
|
||||
|
||||
createdAt time.Time
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
Work *Work
|
||||
Block *types.Block
|
||||
}
|
||||
|
||||
// worker is the main object which takes care of applying messages to the new state
|
||||
@ -92,7 +90,7 @@ type worker struct {
|
||||
mu sync.Mutex
|
||||
|
||||
agents []Agent
|
||||
recv chan *Result
|
||||
recv chan *types.Block
|
||||
mux *event.TypeMux
|
||||
quit chan struct{}
|
||||
pow pow.PoW
|
||||
@ -107,7 +105,7 @@ type worker struct {
|
||||
extra []byte
|
||||
|
||||
currentMu sync.Mutex
|
||||
current *Work
|
||||
current *environment
|
||||
|
||||
uncleMu sync.Mutex
|
||||
possibleUncles map[common.Hash]*types.Block
|
||||
@ -118,8 +116,6 @@ type worker struct {
|
||||
// atomic status counters
|
||||
mining int32
|
||||
atWork int32
|
||||
|
||||
fullValidation bool
|
||||
}
|
||||
|
||||
func newWorker(coinbase common.Address, eth core.Backend) *worker {
|
||||
@ -127,7 +123,7 @@ func newWorker(coinbase common.Address, eth core.Backend) *worker {
|
||||
eth: eth,
|
||||
mux: eth.EventMux(),
|
||||
extraDb: eth.ExtraDb(),
|
||||
recv: make(chan *Result, resultQueueSize),
|
||||
recv: make(chan *types.Block),
|
||||
gasPrice: new(big.Int),
|
||||
chain: eth.ChainManager(),
|
||||
proc: eth.BlockProcessor(),
|
||||
@ -135,7 +131,6 @@ func newWorker(coinbase common.Address, eth core.Backend) *worker {
|
||||
coinbase: coinbase,
|
||||
txQueue: make(map[common.Hash]*types.Transaction),
|
||||
quit: make(chan struct{}),
|
||||
fullValidation: false,
|
||||
}
|
||||
go worker.update()
|
||||
go worker.wait()
|
||||
@ -169,7 +164,7 @@ func (self *worker) pendingBlock() *types.Block {
|
||||
self.current.receipts,
|
||||
)
|
||||
}
|
||||
return self.current.Block
|
||||
return self.current.block
|
||||
}
|
||||
|
||||
func (self *worker) start() {
|
||||
@ -256,55 +251,34 @@ func newLocalMinedBlock(blockNumber uint64, prevMinedBlocks *uint64RingBuffer) (
|
||||
|
||||
func (self *worker) wait() {
|
||||
for {
|
||||
for result := range self.recv {
|
||||
for block := range self.recv {
|
||||
atomic.AddInt32(&self.atWork, -1)
|
||||
|
||||
if result == nil {
|
||||
if block == nil {
|
||||
continue
|
||||
}
|
||||
block := result.Block
|
||||
work := result.Work
|
||||
|
||||
work.state.Sync()
|
||||
if self.fullValidation {
|
||||
if _, err := self.chain.InsertChain(types.Blocks{block}); err != nil {
|
||||
glog.V(logger.Error).Infoln("mining err", err)
|
||||
continue
|
||||
}
|
||||
go self.mux.Post(core.NewMinedBlockEvent{block})
|
||||
} else {
|
||||
parent := self.chain.GetBlock(block.ParentHash())
|
||||
if parent == nil {
|
||||
glog.V(logger.Error).Infoln("Invalid block found during mining")
|
||||
continue
|
||||
}
|
||||
if err := core.ValidateHeader(self.eth.BlockProcessor().Pow, block.Header(), parent, true, false); err != nil && err != core.BlockFutureErr {
|
||||
glog.V(logger.Error).Infoln("Invalid header on mined block:", err)
|
||||
continue
|
||||
}
|
||||
parent := self.chain.GetBlock(block.ParentHash())
|
||||
if parent == nil {
|
||||
glog.V(logger.Error).Infoln("Invalid block found during mining")
|
||||
continue
|
||||
}
|
||||
if err := core.ValidateHeader(self.eth.BlockProcessor().Pow, block.Header(), parent, true); err != nil && err != core.BlockFutureErr {
|
||||
glog.V(logger.Error).Infoln("Invalid header on mined block:", err)
|
||||
continue
|
||||
}
|
||||
|
||||
stat, err := self.chain.WriteBlock(block, false)
|
||||
if err != nil {
|
||||
glog.V(logger.Error).Infoln("error writing block to chain", err)
|
||||
continue
|
||||
}
|
||||
// check if canon block and write transactions
|
||||
if stat == core.CanonStatTy {
|
||||
// This puts transactions in a extra db for rpc
|
||||
core.PutTransactions(self.extraDb, block, block.Transactions())
|
||||
// store the receipts
|
||||
core.PutReceipts(self.extraDb, work.receipts)
|
||||
}
|
||||
|
||||
// broadcast before waiting for validation
|
||||
go func(block *types.Block, logs state.Logs) {
|
||||
self.mux.Post(core.NewMinedBlockEvent{block})
|
||||
self.mux.Post(core.ChainEvent{block, block.Hash(), logs})
|
||||
if stat == core.CanonStatTy {
|
||||
self.mux.Post(core.ChainHeadEvent{block})
|
||||
self.mux.Post(logs)
|
||||
}
|
||||
}(block, work.state.Logs())
|
||||
stat, err := self.chain.WriteBlock(block, false)
|
||||
if err != nil {
|
||||
glog.V(logger.Error).Infoln("error writing block to chain", err)
|
||||
continue
|
||||
}
|
||||
// check if canon block and write transactions
|
||||
if stat == core.CanonStatTy {
|
||||
// This puts transactions in a extra db for rpc
|
||||
core.PutTransactions(self.extraDb, block, block.Transactions())
|
||||
// store the receipts
|
||||
core.PutReceipts(self.extraDb, self.current.receipts)
|
||||
}
|
||||
|
||||
// check staleness and display confirmation
|
||||
@ -314,18 +288,29 @@ func (self *worker) wait() {
|
||||
stale = "stale "
|
||||
} else {
|
||||
confirm = "Wait 5 blocks for confirmation"
|
||||
work.localMinedBlocks = newLocalMinedBlock(block.Number().Uint64(), work.localMinedBlocks)
|
||||
self.current.localMinedBlocks = newLocalMinedBlock(block.Number().Uint64(), self.current.localMinedBlocks)
|
||||
}
|
||||
|
||||
glog.V(logger.Info).Infof("🔨 Mined %sblock (#%v / %x). %s", stale, block.Number(), block.Hash().Bytes()[:4], confirm)
|
||||
|
||||
// broadcast before waiting for validation
|
||||
go func(block *types.Block, logs state.Logs) {
|
||||
self.mux.Post(core.NewMinedBlockEvent{block})
|
||||
self.mux.Post(core.ChainEvent{block, block.Hash(), logs})
|
||||
if stat == core.CanonStatTy {
|
||||
self.mux.Post(core.ChainHeadEvent{block})
|
||||
self.mux.Post(logs)
|
||||
}
|
||||
}(block, self.current.state.Logs())
|
||||
|
||||
self.commitNewWork()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (self *worker) push(work *Work) {
|
||||
func (self *worker) push() {
|
||||
if atomic.LoadInt32(&self.mining) == 1 {
|
||||
if core.Canary(work.state) {
|
||||
if core.Canary(self.current.state) {
|
||||
glog.Infoln("Toxicity levels rising to deadly levels. Your canary has died. You can go back or continue down the mineshaft --more--")
|
||||
glog.Infoln("You turn back and abort mining")
|
||||
return
|
||||
@ -336,7 +321,7 @@ func (self *worker) push(work *Work) {
|
||||
atomic.AddInt32(&self.atWork, 1)
|
||||
|
||||
if agent.Work() != nil {
|
||||
agent.Work() <- work
|
||||
agent.Work() <- self.current.block
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -345,36 +330,35 @@ func (self *worker) push(work *Work) {
|
||||
// makeCurrent creates a new environment for the current cycle.
|
||||
func (self *worker) makeCurrent(parent *types.Block, header *types.Header) {
|
||||
state := state.New(parent.Root(), self.eth.StateDb())
|
||||
work := &Work{
|
||||
current := &environment{
|
||||
state: state,
|
||||
ancestors: set.New(),
|
||||
family: set.New(),
|
||||
uncles: set.New(),
|
||||
header: header,
|
||||
coinbase: state.GetOrNewStateObject(self.coinbase),
|
||||
createdAt: time.Now(),
|
||||
}
|
||||
|
||||
// when 08 is processed ancestors contain 07 (quick block)
|
||||
for _, ancestor := range self.chain.GetBlocksFromHash(parent.Hash(), 7) {
|
||||
for _, uncle := range ancestor.Uncles() {
|
||||
work.family.Add(uncle.Hash())
|
||||
current.family.Add(uncle.Hash())
|
||||
}
|
||||
work.family.Add(ancestor.Hash())
|
||||
work.ancestors.Add(ancestor.Hash())
|
||||
current.family.Add(ancestor.Hash())
|
||||
current.ancestors.Add(ancestor.Hash())
|
||||
}
|
||||
accounts, _ := self.eth.AccountManager().Accounts()
|
||||
|
||||
// Keep track of transactions which return errors so they can be removed
|
||||
work.remove = set.New()
|
||||
work.tcount = 0
|
||||
work.ignoredTransactors = set.New()
|
||||
work.lowGasTransactors = set.New()
|
||||
work.ownedAccounts = accountAddressesSet(accounts)
|
||||
current.remove = set.New()
|
||||
current.tcount = 0
|
||||
current.ignoredTransactors = set.New()
|
||||
current.lowGasTransactors = set.New()
|
||||
current.ownedAccounts = accountAddressesSet(accounts)
|
||||
if self.current != nil {
|
||||
work.localMinedBlocks = self.current.localMinedBlocks
|
||||
current.localMinedBlocks = self.current.localMinedBlocks
|
||||
}
|
||||
self.current = work
|
||||
self.current = current
|
||||
}
|
||||
|
||||
func (w *worker) setGasPrice(p *big.Int) {
|
||||
@ -388,13 +372,13 @@ func (w *worker) setGasPrice(p *big.Int) {
|
||||
w.mux.Post(core.GasPriceChanged{w.gasPrice})
|
||||
}
|
||||
|
||||
func (self *worker) isBlockLocallyMined(current *Work, deepBlockNum uint64) bool {
|
||||
func (self *worker) isBlockLocallyMined(deepBlockNum uint64) bool {
|
||||
//Did this instance mine a block at {deepBlockNum} ?
|
||||
var isLocal = false
|
||||
for idx, blockNum := range current.localMinedBlocks.ints {
|
||||
for idx, blockNum := range self.current.localMinedBlocks.ints {
|
||||
if deepBlockNum == blockNum {
|
||||
isLocal = true
|
||||
current.localMinedBlocks.ints[idx] = 0 //prevent showing duplicate logs
|
||||
self.current.localMinedBlocks.ints[idx] = 0 //prevent showing duplicate logs
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -408,12 +392,12 @@ func (self *worker) isBlockLocallyMined(current *Work, deepBlockNum uint64) bool
|
||||
return block != nil && block.Coinbase() == self.coinbase
|
||||
}
|
||||
|
||||
func (self *worker) logLocalMinedBlocks(current, previous *Work) {
|
||||
if previous != nil && current.localMinedBlocks != nil {
|
||||
nextBlockNum := current.Block.NumberU64()
|
||||
for checkBlockNum := previous.Block.NumberU64(); checkBlockNum < nextBlockNum; checkBlockNum++ {
|
||||
func (self *worker) logLocalMinedBlocks(previous *environment) {
|
||||
if previous != nil && self.current.localMinedBlocks != nil {
|
||||
nextBlockNum := self.current.block.NumberU64()
|
||||
for checkBlockNum := previous.block.NumberU64(); checkBlockNum < nextBlockNum; checkBlockNum++ {
|
||||
inspectBlockNum := checkBlockNum - miningLogAtDepth
|
||||
if self.isBlockLocallyMined(current, inspectBlockNum) {
|
||||
if self.isBlockLocallyMined(inspectBlockNum) {
|
||||
glog.V(logger.Info).Infof("🔨 🔗 Mined %d blocks back: block #%v", miningLogAtDepth, inspectBlockNum)
|
||||
}
|
||||
}
|
||||
@ -431,8 +415,8 @@ func (self *worker) commitNewWork() {
|
||||
tstart := time.Now()
|
||||
parent := self.chain.CurrentBlock()
|
||||
tstamp := tstart.Unix()
|
||||
if parent.Time().Cmp(new(big.Int).SetInt64(tstamp)) >= 0 {
|
||||
tstamp = parent.Time().Int64() + 1
|
||||
if tstamp <= int64(parent.Time()) {
|
||||
tstamp = int64(parent.Time()) + 1
|
||||
}
|
||||
// this will ensure we're not going off too far in the future
|
||||
if now := time.Now().Unix(); tstamp > now+4 {
|
||||
@ -445,57 +429,24 @@ func (self *worker) commitNewWork() {
|
||||
header := &types.Header{
|
||||
ParentHash: parent.Hash(),
|
||||
Number: num.Add(num, common.Big1),
|
||||
Difficulty: core.CalcDifficulty(uint64(tstamp), parent.Time().Uint64(), parent.Number(), parent.Difficulty()),
|
||||
Difficulty: core.CalcDifficulty(uint64(tstamp), parent.Time(), parent.Difficulty()),
|
||||
GasLimit: core.CalcGasLimit(parent),
|
||||
GasUsed: new(big.Int),
|
||||
Coinbase: self.coinbase,
|
||||
Extra: self.extra,
|
||||
Time: big.NewInt(tstamp),
|
||||
Time: uint64(tstamp),
|
||||
}
|
||||
|
||||
previous := self.current
|
||||
self.makeCurrent(parent, header)
|
||||
work := self.current
|
||||
current := self.current
|
||||
|
||||
/* //approach 1
|
||||
// commit transactions for this run.
|
||||
transactions := self.eth.TxPool().GetTransactions()
|
||||
sort.Sort(types.TxByNonce{transactions})
|
||||
*/
|
||||
|
||||
//approach 2
|
||||
transactions := self.eth.TxPool().GetTransactions()
|
||||
sort.Sort(types.TxByPriceAndNonce{transactions})
|
||||
|
||||
/* // approach 3
|
||||
// commit transactions for this run.
|
||||
txPerOwner := make(map[common.Address]types.Transactions)
|
||||
// Sort transactions by owner
|
||||
for _, tx := range self.eth.TxPool().GetTransactions() {
|
||||
from, _ := tx.From() // we can ignore the sender error
|
||||
txPerOwner[from] = append(txPerOwner[from], tx)
|
||||
}
|
||||
var (
|
||||
singleTxOwner types.Transactions
|
||||
multiTxOwner types.Transactions
|
||||
)
|
||||
// Categorise transactions by
|
||||
// 1. 1 owner tx per block
|
||||
// 2. multi txs owner per block
|
||||
for _, txs := range txPerOwner {
|
||||
if len(txs) == 1 {
|
||||
singleTxOwner = append(singleTxOwner, txs[0])
|
||||
} else {
|
||||
multiTxOwner = append(multiTxOwner, txs...)
|
||||
}
|
||||
}
|
||||
sort.Sort(types.TxByPrice{singleTxOwner})
|
||||
sort.Sort(types.TxByNonce{multiTxOwner})
|
||||
transactions := append(singleTxOwner, multiTxOwner...)
|
||||
*/
|
||||
|
||||
work.coinbase.SetGasLimit(header.GasLimit)
|
||||
work.commitTransactions(transactions, self.gasPrice, self.proc)
|
||||
self.eth.TxPool().RemoveTransactions(work.lowGasTxs)
|
||||
current.coinbase.SetGasLimit(header.GasLimit)
|
||||
current.commitTransactions(transactions, self.gasPrice, self.proc)
|
||||
self.eth.TxPool().RemoveTransactions(current.lowGasTxs)
|
||||
|
||||
// compute uncles for the new block.
|
||||
var (
|
||||
@ -506,7 +457,7 @@ func (self *worker) commitNewWork() {
|
||||
if len(uncles) == 2 {
|
||||
break
|
||||
}
|
||||
if err := self.commitUncle(work, uncle.Header()); err != nil {
|
||||
if err := self.commitUncle(uncle.Header()); err != nil {
|
||||
if glog.V(logger.Ridiculousness) {
|
||||
glog.V(logger.Detail).Infof("Bad uncle found and will be removed (%x)\n", hash[:4])
|
||||
glog.V(logger.Detail).Infoln(uncle)
|
||||
@ -523,40 +474,41 @@ func (self *worker) commitNewWork() {
|
||||
|
||||
if atomic.LoadInt32(&self.mining) == 1 {
|
||||
// commit state root after all state transitions.
|
||||
core.AccumulateRewards(work.state, header, uncles)
|
||||
work.state.SyncObjects()
|
||||
header.Root = work.state.Root()
|
||||
core.AccumulateRewards(self.current.state, header, uncles)
|
||||
current.state.SyncObjects()
|
||||
self.current.state.Sync()
|
||||
header.Root = current.state.Root()
|
||||
}
|
||||
|
||||
// create the new block whose nonce will be mined.
|
||||
work.Block = types.NewBlock(header, work.txs, uncles, work.receipts)
|
||||
work.Block.Td = new(big.Int).Set(core.CalcTD(work.Block, self.chain.GetBlock(work.Block.ParentHash())))
|
||||
current.block = types.NewBlock(header, current.txs, uncles, current.receipts)
|
||||
self.current.block.Td = new(big.Int).Set(core.CalcTD(self.current.block, self.chain.GetBlock(self.current.block.ParentHash())))
|
||||
|
||||
// We only care about logging if we're actually mining.
|
||||
if atomic.LoadInt32(&self.mining) == 1 {
|
||||
glog.V(logger.Info).Infof("commit new work on block %v with %d txs & %d uncles. Took %v\n", work.Block.Number(), work.tcount, len(uncles), time.Since(tstart))
|
||||
self.logLocalMinedBlocks(work, previous)
|
||||
glog.V(logger.Info).Infof("commit new work on block %v with %d txs & %d uncles. Took %v\n", current.block.Number(), current.tcount, len(uncles), time.Since(tstart))
|
||||
self.logLocalMinedBlocks(previous)
|
||||
}
|
||||
|
||||
self.push(work)
|
||||
self.push()
|
||||
}
|
||||
|
||||
func (self *worker) commitUncle(work *Work, uncle *types.Header) error {
|
||||
func (self *worker) commitUncle(uncle *types.Header) error {
|
||||
hash := uncle.Hash()
|
||||
if work.uncles.Has(hash) {
|
||||
if self.current.uncles.Has(hash) {
|
||||
return core.UncleError("Uncle not unique")
|
||||
}
|
||||
if !work.ancestors.Has(uncle.ParentHash) {
|
||||
if !self.current.ancestors.Has(uncle.ParentHash) {
|
||||
return core.UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4]))
|
||||
}
|
||||
if work.family.Has(hash) {
|
||||
if self.current.family.Has(hash) {
|
||||
return core.UncleError(fmt.Sprintf("Uncle already in family (%x)", hash))
|
||||
}
|
||||
work.uncles.Add(uncle.Hash())
|
||||
self.current.uncles.Add(uncle.Hash())
|
||||
return nil
|
||||
}
|
||||
|
||||
func (env *Work) commitTransactions(transactions types.Transactions, gasPrice *big.Int, proc *core.BlockProcessor) {
|
||||
func (env *environment) commitTransactions(transactions types.Transactions, gasPrice *big.Int, proc *core.BlockProcessor) {
|
||||
for _, tx := range transactions {
|
||||
// We can skip err. It has already been validated in the tx pool
|
||||
from, _ := tx.From()
|
||||
@ -614,7 +566,7 @@ func (env *Work) commitTransactions(transactions types.Transactions, gasPrice *b
|
||||
}
|
||||
}
|
||||
|
||||
func (env *Work) commitTransaction(tx *types.Transaction, proc *core.BlockProcessor) error {
|
||||
func (env *environment) commitTransaction(tx *types.Transaction, proc *core.BlockProcessor) error {
|
||||
snap := env.state.Copy()
|
||||
receipt, _, err := proc.ApplyTransaction(env.coinbase, env.state, env.header, tx, env.header.GasUsed, true)
|
||||
if err != nil {
|
||||
|
@ -23,7 +23,6 @@ import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/fdtrack"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||
@ -213,7 +212,6 @@ func (t *dialTask) Do(srv *Server) {
|
||||
glog.V(logger.Detail).Infof("dial error: %v", err)
|
||||
return
|
||||
}
|
||||
fd = fdtrack.WrapConn("p2p", fd)
|
||||
mfd := newMeteredConn(fd, false)
|
||||
|
||||
srv.setupConn(mfd, t.flags, t.dest)
|
||||
|
@ -25,7 +25,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/fdtrack"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
"github.com/ethereum/go-ethereum/p2p/nat"
|
||||
@ -198,7 +197,6 @@ func ListenUDP(priv *ecdsa.PrivateKey, laddr string, natm nat.Interface, nodeDBP
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fdtrack.Open("p2p")
|
||||
conn, err := net.ListenUDP("udp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -236,7 +234,6 @@ func newUDP(priv *ecdsa.PrivateKey, c conn, natm nat.Interface, nodeDBPath strin
|
||||
|
||||
func (t *udp) close() {
|
||||
close(t.closing)
|
||||
fdtrack.Close("p2p")
|
||||
t.conn.Close()
|
||||
// TODO: wait for the loops to end.
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ var (
|
||||
// meteredConn is a wrapper around a network TCP connection that meters both the
|
||||
// inbound and outbound network traffic.
|
||||
type meteredConn struct {
|
||||
net.Conn
|
||||
*net.TCPConn // Network connection to wrap with metering
|
||||
}
|
||||
|
||||
// newMeteredConn creates a new metered connection, also bumping the ingress or
|
||||
@ -45,13 +45,13 @@ func newMeteredConn(conn net.Conn, ingress bool) net.Conn {
|
||||
} else {
|
||||
egressConnectMeter.Mark(1)
|
||||
}
|
||||
return &meteredConn{conn}
|
||||
return &meteredConn{conn.(*net.TCPConn)}
|
||||
}
|
||||
|
||||
// Read delegates a network read to the underlying connection, bumping the ingress
|
||||
// traffic meter along the way.
|
||||
func (c *meteredConn) Read(b []byte) (n int, err error) {
|
||||
n, err = c.Conn.Read(b)
|
||||
n, err = c.TCPConn.Read(b)
|
||||
ingressTrafficMeter.Mark(int64(n))
|
||||
return
|
||||
}
|
||||
@ -59,7 +59,7 @@ func (c *meteredConn) Read(b []byte) (n int, err error) {
|
||||
// Write delegates a network write to the underlying connection, bumping the
|
||||
// egress traffic meter along the way.
|
||||
func (c *meteredConn) Write(b []byte) (n int, err error) {
|
||||
n, err = c.Conn.Write(b)
|
||||
n, err = c.TCPConn.Write(b)
|
||||
egressTrafficMeter.Mark(int64(n))
|
||||
return
|
||||
}
|
||||
|
@ -25,7 +25,6 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/fdtrack"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
"github.com/ethereum/go-ethereum/p2p/discover"
|
||||
@ -373,7 +372,7 @@ func (srv *Server) startListening() error {
|
||||
}
|
||||
laddr := listener.Addr().(*net.TCPAddr)
|
||||
srv.ListenAddr = laddr.String()
|
||||
srv.listener = fdtrack.WrapListener("p2p", listener)
|
||||
srv.listener = listener
|
||||
srv.loopWG.Add(1)
|
||||
go srv.listenLoop()
|
||||
// Map the TCP listening port if NAT is configured.
|
||||
|
@ -39,8 +39,8 @@ var (
|
||||
EcrecoverGas = big.NewInt(3000) //
|
||||
Sha256WordGas = big.NewInt(12) //
|
||||
|
||||
MinGasLimit = big.NewInt(5000) // Minimum the gas limit may ever be.
|
||||
GenesisGasLimit = big.NewInt(3141592) // Gas limit of the Genesis block.
|
||||
MinGasLimit = big.NewInt(5000) // Minimum the gas limit may ever be.
|
||||
GenesisGasLimit = big.NewInt(5000) // Gas limit of the Genesis block.
|
||||
|
||||
Sha3Gas = big.NewInt(30) // Once per SHA3 operation.
|
||||
Sha256Gas = big.NewInt(60) //
|
||||
|
@ -935,9 +935,9 @@ func TestCallArgsNotStrings(t *testing.T) {
|
||||
func TestCallArgsToEmpty(t *testing.T) {
|
||||
input := `[{"from": "0xb60e8dd61c5d32be8058bb8eb970870f07233155"}]`
|
||||
args := new(CallArgs)
|
||||
err := json.Unmarshal([]byte(input), &args)
|
||||
if err != nil {
|
||||
t.Error("Did not expect error. Got", err)
|
||||
str := ExpectValidationError(json.Unmarshal([]byte(input), &args))
|
||||
if len(str) > 0 {
|
||||
t.Error(str)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,9 +21,8 @@ import (
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
|
||||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/eth"
|
||||
"github.com/ethereum/go-ethereum/rpc/codec"
|
||||
"github.com/ethereum/go-ethereum/rpc/shared"
|
||||
@ -323,7 +322,7 @@ func (self *ethApi) EstimateGas(req *shared.Request) (interface{}, error) {
|
||||
if len(gas) == 0 {
|
||||
return newHexNum(0), nil
|
||||
} else {
|
||||
return newHexNum(common.String2Big(gas)), err
|
||||
return newHexNum(gas), nil
|
||||
}
|
||||
}
|
||||
|
||||
@ -579,17 +578,14 @@ func (self *ethApi) Resend(req *shared.Request) (interface{}, error) {
|
||||
return nil, shared.NewDecodeParamError(err.Error())
|
||||
}
|
||||
|
||||
from := common.HexToAddress(args.Tx.From)
|
||||
|
||||
pending := self.ethereum.TxPool().GetTransactions()
|
||||
for _, p := range pending {
|
||||
if pFrom, err := p.From(); err == nil && pFrom == from && p.SigHash() == args.Tx.tx.SigHash() {
|
||||
self.ethereum.TxPool().RemoveTx(common.HexToHash(args.Tx.Hash))
|
||||
return self.xeth.Transact(args.Tx.From, args.Tx.To, args.Tx.Nonce, args.Tx.Value, args.GasLimit, args.GasPrice, args.Tx.Data)
|
||||
}
|
||||
ret, err := self.xeth.Transact(args.Tx.From, args.Tx.To, args.Tx.Nonce, args.Tx.Value, args.GasLimit, args.GasPrice, args.Tx.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("Transaction %s not found", args.Tx.Hash)
|
||||
self.ethereum.TxPool().RemoveTransactions(types.Transactions{args.Tx.tx})
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *ethApi) PendingTransactions(req *shared.Request) (interface{}, error) {
|
||||
|
@ -469,6 +469,10 @@ func (args *CallArgs) UnmarshalJSON(b []byte) (err error) {
|
||||
}
|
||||
|
||||
args.From = ext.From
|
||||
|
||||
if len(ext.To) == 0 {
|
||||
return shared.NewValidationError("to", "is required")
|
||||
}
|
||||
args.To = ext.To
|
||||
|
||||
var num *big.Int
|
||||
@ -884,7 +888,6 @@ type tx struct {
|
||||
Data string
|
||||
GasLimit string
|
||||
GasPrice string
|
||||
Hash string
|
||||
}
|
||||
|
||||
func newTx(t *types.Transaction) *tx {
|
||||
@ -903,7 +906,6 @@ func newTx(t *types.Transaction) *tx {
|
||||
Data: "0x" + common.Bytes2Hex(t.Data()),
|
||||
GasLimit: t.Gas().String(),
|
||||
GasPrice: t.GasPrice().String(),
|
||||
Hash: t.Hash().Hex(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -929,12 +931,6 @@ func (tx *tx) UnmarshalJSON(b []byte) (err error) {
|
||||
contractCreation = true
|
||||
)
|
||||
|
||||
if val, found := fields["Hash"]; found {
|
||||
if hashVal, ok := val.(string); ok {
|
||||
tx.Hash = hashVal
|
||||
}
|
||||
}
|
||||
|
||||
if val, found := fields["To"]; found {
|
||||
if strVal, ok := val.(string); ok && len(strVal) > 0 {
|
||||
tx.To = strVal
|
||||
|
@ -32,22 +32,16 @@ var (
|
||||
AutoCompletion = map[string][]string{
|
||||
"admin": []string{
|
||||
"addPeer",
|
||||
"chainSyncStatus",
|
||||
"datadir",
|
||||
"exportChain",
|
||||
"getContractInfo",
|
||||
"importChain",
|
||||
"nodeInfo",
|
||||
"peers",
|
||||
"register",
|
||||
"registerUrl",
|
||||
"setSolc",
|
||||
"sleepBlocks",
|
||||
"startNatSpec",
|
||||
"startRPC",
|
||||
"stopNatSpec",
|
||||
"stopRPC",
|
||||
"nodeInfo",
|
||||
"exportChain",
|
||||
"importChain",
|
||||
"verbosity",
|
||||
"chainSyncStatus",
|
||||
"setSolc",
|
||||
"datadir",
|
||||
"startRPC",
|
||||
"stopRPC",
|
||||
},
|
||||
"db": []string{
|
||||
"getString",
|
||||
@ -103,7 +97,6 @@ var (
|
||||
"miner": []string{
|
||||
"hashrate",
|
||||
"makeDAG",
|
||||
"setEtherbase",
|
||||
"setExtra",
|
||||
"setGasPrice",
|
||||
"startAutoDAG",
|
||||
|
@ -17,19 +17,13 @@
|
||||
package comms
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"bytes"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
||||
"github.com/ethereum/go-ethereum/fdtrack"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
"github.com/ethereum/go-ethereum/rpc/codec"
|
||||
@ -37,15 +31,10 @@ import (
|
||||
"github.com/rs/cors"
|
||||
)
|
||||
|
||||
const (
|
||||
serverIdleTimeout = 10 * time.Second // idle keep-alive connections
|
||||
serverReadTimeout = 15 * time.Second // per-request read timeout
|
||||
serverWriteTimeout = 15 * time.Second // per-request read timeout
|
||||
)
|
||||
|
||||
var (
|
||||
httpServerMu sync.Mutex
|
||||
httpServer *stopServer
|
||||
// main HTTP rpc listener
|
||||
httpListener *stoppableTCPListener
|
||||
listenerStoppedError = fmt.Errorf("Listener has stopped")
|
||||
)
|
||||
|
||||
type HttpConfig struct {
|
||||
@ -54,172 +43,42 @@ type HttpConfig struct {
|
||||
CorsDomain string
|
||||
}
|
||||
|
||||
// stopServer augments http.Server with idle connection tracking.
|
||||
// Idle keep-alive connections are shut down when Close is called.
|
||||
type stopServer struct {
|
||||
*http.Server
|
||||
l net.Listener
|
||||
// connection tracking state
|
||||
mu sync.Mutex
|
||||
shutdown bool // true when Stop has returned
|
||||
idle map[net.Conn]struct{}
|
||||
}
|
||||
|
||||
type handler struct {
|
||||
codec codec.Codec
|
||||
api shared.EthereumApi
|
||||
}
|
||||
|
||||
// StartHTTP starts listening for RPC requests sent via HTTP.
|
||||
func StartHttp(cfg HttpConfig, codec codec.Codec, api shared.EthereumApi) error {
|
||||
httpServerMu.Lock()
|
||||
defer httpServerMu.Unlock()
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", cfg.ListenAddress, cfg.ListenPort)
|
||||
if httpServer != nil {
|
||||
if addr != httpServer.Addr {
|
||||
return fmt.Errorf("RPC service already running on %s ", httpServer.Addr)
|
||||
if httpListener != nil {
|
||||
if fmt.Sprintf("%s:%d", cfg.ListenAddress, cfg.ListenPort) != httpListener.Addr().String() {
|
||||
return fmt.Errorf("RPC service already running on %s ", httpListener.Addr().String())
|
||||
}
|
||||
return nil // RPC service already running on given host/port
|
||||
}
|
||||
// Set up the request handler, wrapping it with CORS headers if configured.
|
||||
handler := http.Handler(&handler{codec, api})
|
||||
if len(cfg.CorsDomain) > 0 {
|
||||
opts := cors.Options{
|
||||
AllowedMethods: []string{"POST"},
|
||||
AllowedOrigins: strings.Split(cfg.CorsDomain, " "),
|
||||
}
|
||||
handler = cors.New(opts).Handler(handler)
|
||||
}
|
||||
// Start the server.
|
||||
s, err := listenHTTP(addr, handler)
|
||||
|
||||
l, err := newStoppableTCPListener(fmt.Sprintf("%s:%d", cfg.ListenAddress, cfg.ListenPort))
|
||||
if err != nil {
|
||||
glog.V(logger.Error).Infof("Can't listen on %s:%d: %v", cfg.ListenAddress, cfg.ListenPort, err)
|
||||
return err
|
||||
}
|
||||
httpServer = s
|
||||
httpListener = l
|
||||
|
||||
var handler http.Handler
|
||||
if len(cfg.CorsDomain) > 0 {
|
||||
var opts cors.Options
|
||||
opts.AllowedMethods = []string{"POST"}
|
||||
opts.AllowedOrigins = strings.Split(cfg.CorsDomain, " ")
|
||||
|
||||
c := cors.New(opts)
|
||||
handler = newStoppableHandler(c.Handler(gethHttpHandler(codec, api)), l.stop)
|
||||
} else {
|
||||
handler = newStoppableHandler(gethHttpHandler(codec, api), l.stop)
|
||||
}
|
||||
|
||||
go http.Serve(l, handler)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (h *handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
// Limit request size to resist DoS
|
||||
if req.ContentLength > maxHttpSizeReqLength {
|
||||
err := fmt.Errorf("Request too large")
|
||||
response := shared.NewRpcErrorResponse(-1, shared.JsonRpcVersion, -32700, err)
|
||||
sendJSON(w, &response)
|
||||
return
|
||||
}
|
||||
|
||||
defer req.Body.Close()
|
||||
payload, err := ioutil.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Could not read request body")
|
||||
response := shared.NewRpcErrorResponse(-1, shared.JsonRpcVersion, -32700, err)
|
||||
sendJSON(w, &response)
|
||||
return
|
||||
}
|
||||
|
||||
c := h.codec.New(nil)
|
||||
var rpcReq shared.Request
|
||||
if err = c.Decode(payload, &rpcReq); err == nil {
|
||||
reply, err := h.api.Execute(&rpcReq)
|
||||
res := shared.NewRpcResponse(rpcReq.Id, rpcReq.Jsonrpc, reply, err)
|
||||
sendJSON(w, &res)
|
||||
return
|
||||
}
|
||||
|
||||
var reqBatch []shared.Request
|
||||
if err = c.Decode(payload, &reqBatch); err == nil {
|
||||
resBatch := make([]*interface{}, len(reqBatch))
|
||||
resCount := 0
|
||||
for i, rpcReq := range reqBatch {
|
||||
reply, err := h.api.Execute(&rpcReq)
|
||||
if rpcReq.Id != nil { // this leaves nil entries in the response batch for later removal
|
||||
resBatch[i] = shared.NewRpcResponse(rpcReq.Id, rpcReq.Jsonrpc, reply, err)
|
||||
resCount += 1
|
||||
}
|
||||
}
|
||||
// make response omitting nil entries
|
||||
sendJSON(w, resBatch[:resCount])
|
||||
return
|
||||
}
|
||||
|
||||
// invalid request
|
||||
err = fmt.Errorf("Could not decode request")
|
||||
res := shared.NewRpcErrorResponse(-1, shared.JsonRpcVersion, -32600, err)
|
||||
sendJSON(w, res)
|
||||
}
|
||||
|
||||
func sendJSON(w io.Writer, v interface{}) {
|
||||
if glog.V(logger.Detail) {
|
||||
if payload, err := json.MarshalIndent(v, "", "\t"); err == nil {
|
||||
glog.Infof("Sending payload: %s", payload)
|
||||
}
|
||||
}
|
||||
if err := json.NewEncoder(w).Encode(v); err != nil {
|
||||
glog.V(logger.Error).Infoln("Error sending JSON:", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Stop closes all active HTTP connections and shuts down the server.
|
||||
func StopHttp() {
|
||||
httpServerMu.Lock()
|
||||
defer httpServerMu.Unlock()
|
||||
if httpServer != nil {
|
||||
httpServer.Close()
|
||||
httpServer = nil
|
||||
}
|
||||
}
|
||||
|
||||
func listenHTTP(addr string, h http.Handler) (*stopServer, error) {
|
||||
l, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
l = fdtrack.WrapListener("rpc", l)
|
||||
s := &stopServer{l: l, idle: make(map[net.Conn]struct{})}
|
||||
s.Server = &http.Server{
|
||||
Addr: addr,
|
||||
Handler: h,
|
||||
ReadTimeout: serverReadTimeout,
|
||||
WriteTimeout: serverWriteTimeout,
|
||||
ConnState: s.connState,
|
||||
}
|
||||
go s.Serve(l)
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *stopServer) connState(c net.Conn, state http.ConnState) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
// Close c immediately if we're past shutdown.
|
||||
if s.shutdown {
|
||||
if state != http.StateClosed {
|
||||
c.Close()
|
||||
}
|
||||
return
|
||||
}
|
||||
if state == http.StateIdle {
|
||||
s.idle[c] = struct{}{}
|
||||
} else {
|
||||
delete(s.idle, c)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *stopServer) Close() {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
// Shut down the acceptor. No new connections can be created.
|
||||
s.l.Close()
|
||||
// Drop all idle connections. Non-idle connections will be
|
||||
// closed by connState as soon as they become idle.
|
||||
s.shutdown = true
|
||||
for c := range s.idle {
|
||||
glog.V(logger.Detail).Infof("closing idle connection %v", c.RemoteAddr())
|
||||
c.Close()
|
||||
delete(s.idle, c)
|
||||
if httpListener != nil {
|
||||
httpListener.Stop()
|
||||
httpListener = nil
|
||||
}
|
||||
}
|
||||
|
||||
|
182
rpc/comms/http_net.go
Normal file
182
rpc/comms/http_net.go
Normal file
@ -0,0 +1,182 @@
|
||||
// Copyright 2015 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package comms
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
"github.com/ethereum/go-ethereum/rpc/codec"
|
||||
"github.com/ethereum/go-ethereum/rpc/shared"
|
||||
)
|
||||
|
||||
// When https://github.com/golang/go/issues/4674 is implemented this could be replaced
|
||||
type stoppableTCPListener struct {
|
||||
*net.TCPListener
|
||||
stop chan struct{} // closed when the listener must stop
|
||||
}
|
||||
|
||||
func newStoppableTCPListener(addr string) (*stoppableTCPListener, error) {
|
||||
wl, err := net.Listen("tcp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if tcpl, ok := wl.(*net.TCPListener); ok {
|
||||
stop := make(chan struct{})
|
||||
return &stoppableTCPListener{tcpl, stop}, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("Unable to create TCP listener for RPC service")
|
||||
}
|
||||
|
||||
// Stop the listener and all accepted and still active connections.
|
||||
func (self *stoppableTCPListener) Stop() {
|
||||
close(self.stop)
|
||||
}
|
||||
|
||||
func (self *stoppableTCPListener) Accept() (net.Conn, error) {
|
||||
for {
|
||||
self.SetDeadline(time.Now().Add(time.Duration(1 * time.Second)))
|
||||
c, err := self.TCPListener.AcceptTCP()
|
||||
|
||||
select {
|
||||
case <-self.stop:
|
||||
if c != nil { // accept timeout
|
||||
c.Close()
|
||||
}
|
||||
self.TCPListener.Close()
|
||||
return nil, listenerStoppedError
|
||||
default:
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() && netErr.Temporary() {
|
||||
continue // regular timeout
|
||||
}
|
||||
}
|
||||
|
||||
return &closableConnection{c, self.stop}, err
|
||||
}
|
||||
}
|
||||
|
||||
type closableConnection struct {
|
||||
*net.TCPConn
|
||||
closed chan struct{}
|
||||
}
|
||||
|
||||
func (self *closableConnection) Read(b []byte) (n int, err error) {
|
||||
select {
|
||||
case <-self.closed:
|
||||
self.TCPConn.Close()
|
||||
return 0, io.EOF
|
||||
default:
|
||||
return self.TCPConn.Read(b)
|
||||
}
|
||||
}
|
||||
|
||||
// Wraps the default handler and checks if the RPC service was stopped. In that case it returns an
|
||||
// error indicating that the service was stopped. This will only happen for connections which are
|
||||
// kept open (HTTP keep-alive) when the RPC service was shutdown.
|
||||
func newStoppableHandler(h http.Handler, stop chan struct{}) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
select {
|
||||
case <-stop:
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
err := fmt.Errorf("RPC service stopped")
|
||||
response := shared.NewRpcResponse(-1, shared.JsonRpcVersion, nil, err)
|
||||
httpSend(w, response)
|
||||
default:
|
||||
h.ServeHTTP(w, r)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func httpSend(writer io.Writer, v interface{}) (n int, err error) {
|
||||
var payload []byte
|
||||
payload, err = json.MarshalIndent(v, "", "\t")
|
||||
if err != nil {
|
||||
glog.V(logger.Error).Infoln("Error marshalling JSON", err)
|
||||
return 0, err
|
||||
}
|
||||
glog.V(logger.Detail).Infof("Sending payload: %s", payload)
|
||||
|
||||
return writer.Write(payload)
|
||||
}
|
||||
|
||||
func gethHttpHandler(codec codec.Codec, a shared.EthereumApi) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
// Limit request size to resist DoS
|
||||
if req.ContentLength > maxHttpSizeReqLength {
|
||||
err := fmt.Errorf("Request too large")
|
||||
response := shared.NewRpcErrorResponse(-1, shared.JsonRpcVersion, -32700, err)
|
||||
httpSend(w, &response)
|
||||
return
|
||||
}
|
||||
|
||||
defer req.Body.Close()
|
||||
payload, err := ioutil.ReadAll(req.Body)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Could not read request body")
|
||||
response := shared.NewRpcErrorResponse(-1, shared.JsonRpcVersion, -32700, err)
|
||||
httpSend(w, &response)
|
||||
return
|
||||
}
|
||||
|
||||
c := codec.New(nil)
|
||||
var rpcReq shared.Request
|
||||
if err = c.Decode(payload, &rpcReq); err == nil {
|
||||
reply, err := a.Execute(&rpcReq)
|
||||
res := shared.NewRpcResponse(rpcReq.Id, rpcReq.Jsonrpc, reply, err)
|
||||
httpSend(w, &res)
|
||||
return
|
||||
}
|
||||
|
||||
var reqBatch []shared.Request
|
||||
if err = c.Decode(payload, &reqBatch); err == nil {
|
||||
resBatch := make([]*interface{}, len(reqBatch))
|
||||
resCount := 0
|
||||
|
||||
for i, rpcReq := range reqBatch {
|
||||
reply, err := a.Execute(&rpcReq)
|
||||
if rpcReq.Id != nil { // this leaves nil entries in the response batch for later removal
|
||||
resBatch[i] = shared.NewRpcResponse(rpcReq.Id, rpcReq.Jsonrpc, reply, err)
|
||||
resCount += 1
|
||||
}
|
||||
}
|
||||
|
||||
// make response omitting nil entries
|
||||
resBatch = resBatch[:resCount]
|
||||
httpSend(w, resBatch)
|
||||
return
|
||||
}
|
||||
|
||||
// invalid request
|
||||
err = fmt.Errorf("Could not decode request")
|
||||
res := shared.NewRpcErrorResponse(-1, shared.JsonRpcVersion, -32600, err)
|
||||
httpSend(w, res)
|
||||
})
|
||||
}
|
@ -22,7 +22,6 @@ import (
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/ethereum/go-ethereum/fdtrack"
|
||||
"github.com/ethereum/go-ethereum/logger"
|
||||
"github.com/ethereum/go-ethereum/logger/glog"
|
||||
"github.com/ethereum/go-ethereum/rpc/codec"
|
||||
@ -51,16 +50,15 @@ func (self *ipcClient) reconnect() error {
|
||||
func startIpc(cfg IpcConfig, codec codec.Codec, api shared.EthereumApi) error {
|
||||
os.Remove(cfg.Endpoint) // in case it still exists from a previous run
|
||||
|
||||
l, err := net.Listen("unix", cfg.Endpoint)
|
||||
l, err := net.ListenUnix("unix", &net.UnixAddr{Name: cfg.Endpoint, Net: "unix"})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
l = fdtrack.WrapListener("ipc", l)
|
||||
os.Chmod(cfg.Endpoint, 0600)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
conn, err := l.Accept()
|
||||
conn, err := l.AcceptUnix()
|
||||
if err != nil {
|
||||
glog.V(logger.Error).Infof("Error accepting ipc connection - %v\n", err)
|
||||
continue
|
||||
|
@ -35,13 +35,6 @@ func TestBcUncleHeaderValidityTests(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBcUncleTests(t *testing.T) {
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcUncleTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBcInvalidHeaderTests(t *testing.T) {
|
||||
err := RunBlockTest(filepath.Join(blockTestDir, "bcInvalidHeaderTest.json"), BlockSkipTests)
|
||||
if err != nil {
|
||||
|
@ -150,7 +150,7 @@ func runBlockTests(bt map[string]*BlockTest, skipTests []string) error {
|
||||
|
||||
// test the block
|
||||
if err := runBlockTest(test); err != nil {
|
||||
return fmt.Errorf("%s: %v", name, err)
|
||||
return err
|
||||
}
|
||||
glog.Infoln("Block test passed: ", name)
|
||||
|
||||
@ -365,8 +365,8 @@ func (s *BlockTest) validateBlockHeader(h *btHeader, h2 *types.Header) error {
|
||||
return fmt.Errorf("GasUsed: expected: %v, decoded: %v", expectedGasUsed, h2.GasUsed)
|
||||
}
|
||||
|
||||
expectedTimestamp := mustConvertBigInt(h.Timestamp, 16)
|
||||
if expectedTimestamp.Cmp(h2.Time) != 0 {
|
||||
expectedTimestamp := mustConvertUint(h.Timestamp, 16)
|
||||
if expectedTimestamp != h2.Time {
|
||||
return fmt.Errorf("Timestamp: expected: %v, decoded: %v", expectedTimestamp, h2.Time)
|
||||
}
|
||||
|
||||
@ -461,7 +461,7 @@ func mustConvertHeader(in btHeader) *types.Header {
|
||||
GasUsed: mustConvertBigInt(in.GasUsed, 16),
|
||||
GasLimit: mustConvertBigInt(in.GasLimit, 16),
|
||||
Difficulty: mustConvertBigInt(in.Difficulty, 16),
|
||||
Time: mustConvertBigInt(in.Timestamp, 16),
|
||||
Time: mustConvertUint(in.Timestamp, 16),
|
||||
Nonce: types.EncodeNonce(mustConvertUint(in.Nonce, 16)),
|
||||
}
|
||||
return header
|
||||
|
@ -1,100 +0,0 @@
|
||||
{
|
||||
"preExpDiffIncrease" : {
|
||||
"parentTimestamp" : "42",
|
||||
"parentDifficulty" : "1000000",
|
||||
"currentTimestamp" : "43",
|
||||
"currentBlockNumber" : "42",
|
||||
"currentDifficulty" : "1000488"
|
||||
},
|
||||
"preExpDiffDecrease" : {
|
||||
"parentTimestamp" : "42",
|
||||
"parentDifficulty" : "1000000",
|
||||
"currentTimestamp" : "60",
|
||||
"currentBlockNumber" : "42",
|
||||
"currentDifficulty" : "999512"
|
||||
},
|
||||
"ExpDiffAtBlock200000Increase" : {
|
||||
"parentTimestamp" : "42",
|
||||
"parentDifficulty" : "1000000",
|
||||
"currentTimestamp" : "43",
|
||||
"currentBlockNumber" : "200000",
|
||||
"currentDifficulty" : "1000489"
|
||||
},
|
||||
"ExpDiffAtBlock200000Decrease" : {
|
||||
"parentTimestamp" : "42",
|
||||
"parentDifficulty" : "1000000",
|
||||
"currentTimestamp" : "60",
|
||||
"currentBlockNumber" : "200000",
|
||||
"currentDifficulty" : "999513"
|
||||
},
|
||||
"ExpDiffPostBlock200000Increase" : {
|
||||
"parentTimestamp" : "42",
|
||||
"parentDifficulty" : "1000000",
|
||||
"currentTimestamp" : "43",
|
||||
"currentBlockNumber" : "200001",
|
||||
"currentDifficulty" : "1000489"
|
||||
},
|
||||
"ExpDiffPostBlock200000Decrease" : {
|
||||
"parentTimestamp" : "42",
|
||||
"parentDifficulty" : "1000000",
|
||||
"currentTimestamp" : "60",
|
||||
"currentBlockNumber" : "200001",
|
||||
"currentDifficulty" : "999513"
|
||||
},
|
||||
"ExpDiffPreBlock300000Increase" : {
|
||||
"parentTimestamp" : "42",
|
||||
"parentDifficulty" : "1000000",
|
||||
"currentTimestamp" : "43",
|
||||
"currentBlockNumber" : "299999",
|
||||
"currentDifficulty" : "1000489"
|
||||
},
|
||||
"ExpDiffPreBlock300000Decrease" : {
|
||||
"parentTimestamp" : "42",
|
||||
"parentDifficulty" : "1000000",
|
||||
"currentTimestamp" : "60",
|
||||
"currentBlockNumber" : "299999",
|
||||
"currentDifficulty" : "999513"
|
||||
},
|
||||
"ExpDiffAtBlock300000Increase" : {
|
||||
"parentTimestamp" : "42",
|
||||
"parentDifficulty" : "1000000",
|
||||
"currentTimestamp" : "43",
|
||||
"currentBlockNumber" : "300000",
|
||||
"currentDifficulty" : "1000490"
|
||||
},
|
||||
"ExpDiffAtBlock300000Decrease" : {
|
||||
"parentTimestamp" : "42",
|
||||
"parentDifficulty" : "1000000",
|
||||
"currentTimestamp" : "60",
|
||||
"currentBlockNumber" : "300000",
|
||||
"currentDifficulty" : "999514"
|
||||
},
|
||||
"ExpDiffPostBlock300000Increase" : {
|
||||
"parentTimestamp" : "42",
|
||||
"parentDifficulty" : "1000000",
|
||||
"currentTimestamp" : "43",
|
||||
"currentBlockNumber" : "300001",
|
||||
"currentDifficulty" : "1000490"
|
||||
},
|
||||
"ExpDiffPostBlock300000Decrease" : {
|
||||
"parentTimestamp" : "42",
|
||||
"parentDifficulty" : "1000000",
|
||||
"currentTimestamp" : "60",
|
||||
"currentBlockNumber" : "300001",
|
||||
"currentDifficulty" : "999514"
|
||||
},
|
||||
"ExpDiffInAYearIncrease" : {
|
||||
"parentTimestamp" : "42",
|
||||
"parentDifficulty" : "1000000",
|
||||
"currentTimestamp" : "43",
|
||||
"currentBlockNumber" : "2302400",
|
||||
"currentDifficulty" : "3097640"
|
||||
},
|
||||
"ExpDiffInAYearDecrease" : {
|
||||
"parentTimestamp" : "42",
|
||||
"parentDifficulty" : "1000000",
|
||||
"currentTimestamp" : "60",
|
||||
"currentBlockNumber" : "2302400",
|
||||
"currentDifficulty" : "3096664"
|
||||
}
|
||||
}
|
@ -4543,318 +4543,5 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"uncleTimestampTooBig" : {
|
||||
"blocks" : [
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020000",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefd8",
|
||||
"gasUsed" : "0x5208",
|
||||
"hash" : "6bd328a10bb674cc758bd1bccb8afb584808766434c28b85580b422c75d4130e",
|
||||
"mixHash" : "fefce638471ab6b66b1f1423ae574a99a6b2137229fe1846c508554d718d2bc1",
|
||||
"nonce" : "f8cf2912afdd244d",
|
||||
"number" : "0x01",
|
||||
"parentHash" : "b964d0b68e5a3c7265e4087dc2a8aaf599f06b6d6c1316a1b1b6475587f569e2",
|
||||
"receiptTrie" : "e9244cf7503b79c03d3a099e07a80d2dbc77bb0b502d8a89d51ac0d68dd31313",
|
||||
"stateRoot" : "cb52de543653d86ccd13ba3ddf8b052525b04231c6884a4db3188a184681d878",
|
||||
"timestamp" : "0x55d9d69f",
|
||||
"transactionsTrie" : "5c9151c2413d1cd25c51ffb4ac38948acc1359bf08c6b49f283660e9bcf0f516",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"rlp" : "0xf90261f901f9a0b964d0b68e5a3c7265e4087dc2a8aaf599f06b6d6c1316a1b1b6475587f569e2a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0cb52de543653d86ccd13ba3ddf8b052525b04231c6884a4db3188a184681d878a05c9151c2413d1cd25c51ffb4ac38948acc1359bf08c6b49f283660e9bcf0f516a0e9244cf7503b79c03d3a099e07a80d2dbc77bb0b502d8a89d51ac0d68dd31313b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd88252088455d9d69f80a0fefce638471ab6b66b1f1423ae574a99a6b2137229fe1846c508554d718d2bc188f8cf2912afdd244df862f86080018304cb2f94095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba077c7cd36820c71821c1aed59de46e70e701c4a8dd89c9ba508ab722210f60da8a03f29825d40c7c3f7bff3ca69267e0f3fb74b2d18b8c2c4e3c135b5d3b06e288dc0",
|
||||
"transactions" : [
|
||||
{
|
||||
"data" : "0x",
|
||||
"gasLimit" : "0x04cb2f",
|
||||
"gasPrice" : "0x01",
|
||||
"nonce" : "0x00",
|
||||
"r" : "0x77c7cd36820c71821c1aed59de46e70e701c4a8dd89c9ba508ab722210f60da8",
|
||||
"s" : "0x3f29825d40c7c3f7bff3ca69267e0f3fb74b2d18b8c2c4e3c135b5d3b06e288d",
|
||||
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
|
||||
"v" : "0x1b",
|
||||
"value" : "0x0a"
|
||||
}
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020040",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefd8",
|
||||
"gasUsed" : "0x5208",
|
||||
"hash" : "4c179927c9b9897464c7133033b412c9b66ee2bb1fa4a4b2595a6006d4081e3f",
|
||||
"mixHash" : "3449cf46635bab4ae7121dcd145e6ca12ac4337f79e88354c41bff1c48335b48",
|
||||
"nonce" : "4376da5cd48ffb68",
|
||||
"number" : "0x02",
|
||||
"parentHash" : "6bd328a10bb674cc758bd1bccb8afb584808766434c28b85580b422c75d4130e",
|
||||
"receiptTrie" : "5ea1a8b24652fed0ecab4738edd9211891eb8c4353c345973b78a02cc0f32f6b",
|
||||
"stateRoot" : "e7e4760f75476ec7f51869d8bdce5c693058fd5a95c77ea9c0bf7ced1e50d70e",
|
||||
"timestamp" : "0x55d9d6a1",
|
||||
"transactionsTrie" : "c673e076264c4669a5c2e479f1757b78e42511efe33b5fd2c0a23b929c7f87f5",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"rlp" : "0xf90260f901f9a06bd328a10bb674cc758bd1bccb8afb584808766434c28b85580b422c75d4130ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0e7e4760f75476ec7f51869d8bdce5c693058fd5a95c77ea9c0bf7ced1e50d70ea0c673e076264c4669a5c2e479f1757b78e42511efe33b5fd2c0a23b929c7f87f5a05ea1a8b24652fed0ecab4738edd9211891eb8c4353c345973b78a02cc0f32f6bb90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004002832fefd88252088455d9d6a180a03449cf46635bab4ae7121dcd145e6ca12ac4337f79e88354c41bff1c48335b48884376da5cd48ffb68f861f85f01018304cb2f94095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba033c86e64d708c97c6b135cadff79dbf45985aa0b53694789e90d15f756765f239f1d0f8caa2a16405148c9d85581be5814960010f3cba938b5501590cea1f7cfc0",
|
||||
"transactions" : [
|
||||
{
|
||||
"data" : "0x",
|
||||
"gasLimit" : "0x04cb2f",
|
||||
"gasPrice" : "0x01",
|
||||
"nonce" : "0x01",
|
||||
"r" : "0x33c86e64d708c97c6b135cadff79dbf45985aa0b53694789e90d15f756765f23",
|
||||
"s" : "0x1d0f8caa2a16405148c9d85581be5814960010f3cba938b5501590cea1f7cf",
|
||||
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
|
||||
"v" : "0x1b",
|
||||
"value" : "0x0a"
|
||||
}
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"rlp" : "0xf90459f901f9a04c179927c9b9897464c7133033b412c9b66ee2bb1fa4a4b2595a6006d4081e3fa0f4fd3b99eb9b343e87bc472fdcd6b18e5cbcb231b1e70f8948e97b02c008ac26948888f1f195afa192cfee860698584c030f4c9db1a0e9940294a09308406a3d2e09203aed11db40259fac0a25e639ad2b30b82d07dea01722b8a91bfc4f5614ce36ee77c7cce6620ab4af36d3c54baa66d7dbeb7bce1aa04ede0225773c7a517b91994aca65ade45124e7ef4b8be1e6097c9773a11920afb90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefd88252088455d9d6a680a0caf6f553d8c1394d291caaeabc61bc25f9126f4c313c829b2a51134cbd23d27188e6999e52421f5a38f862f86002018304cb2f94095e7baea6a6c7c4c2dfeb977efac326af552d870a801ca015eb1cc916728b9799e55c489857727669afb2986433d5f54cde11faaed9f0eea05d36f6d06c34aae8d0a2a5895c8ba4a17ad46a5fa59f361cb3e7e01a23030e38f901f6f901f3a06bd328a10bb674cc758bd1bccb8afb584808766434c28b85580b422c75d4130ea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794bcde5374fce5edbc8e2a8697c15331677e6ebf0ba0cb52de543653d86ccd13ba3ddf8b052525b04231c6884a4db3188a184681d878a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000002832fefd8808080a077355633b05269548d6b3bd8e80d334fcb1a31c566b980dfc56eb57d5c16acc388846c622f81a727e7"
|
||||
}
|
||||
],
|
||||
"genesisBlockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020000",
|
||||
"extraData" : "0x42",
|
||||
"gasLimit" : "0x2fefd8",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "b964d0b68e5a3c7265e4087dc2a8aaf599f06b6d6c1316a1b1b6475587f569e2",
|
||||
"mixHash" : "b65f3c17c458ce015c087c3e4c0ffeeb010bf648a1faa2585c674d81ea7dcdfd",
|
||||
"nonce" : "0b2ec3394d2421e3",
|
||||
"number" : "0x00",
|
||||
"parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "7dba07d6b448a186e9612e5f737d1c909dce473e53199901a302c00646d523c1",
|
||||
"timestamp" : "0x54c98c81",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a07dba07d6b448a186e9612e5f737d1c909dce473e53199901a302c00646d523c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808454c98c8142a0b65f3c17c458ce015c087c3e4c0ffeeb010bf648a1faa2585c674d81ea7dcdfd880b2ec3394d2421e3c0c0",
|
||||
"lastblockhash" : "4c179927c9b9897464c7133033b412c9b66ee2bb1fa4a4b2595a6006d4081e3f",
|
||||
"postState" : {
|
||||
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
|
||||
"balance" : "0x14",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
},
|
||||
"8888f1f195afa192cfee860698584c030f4c9db1" : {
|
||||
"balance" : "0x8ac7230489e8a410",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
},
|
||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x09184e71fbdc",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x02",
|
||||
"storage" : {
|
||||
}
|
||||
}
|
||||
},
|
||||
"pre" : {
|
||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x09184e72a000",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"uncleTimestampMaxUint256" : {
|
||||
"blocks" : [
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020000",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefd8",
|
||||
"gasUsed" : "0x5208",
|
||||
"hash" : "19c900975f94fd78dc12ad13740200fbe0a2eba43fd070bedc65588b0c95438a",
|
||||
"mixHash" : "4296af28ea723598c959f1cabc6f01fa0c75d126cfde89f13ccd9debcf3079c3",
|
||||
"nonce" : "3213b3fd7789f5d5",
|
||||
"number" : "0x01",
|
||||
"parentHash" : "e688d736f1307c6f97b6777381b30556137b9d4ca5c43fbd5b30d6b5df315264",
|
||||
"receiptTrie" : "e9244cf7503b79c03d3a099e07a80d2dbc77bb0b502d8a89d51ac0d68dd31313",
|
||||
"stateRoot" : "cb52de543653d86ccd13ba3ddf8b052525b04231c6884a4db3188a184681d878",
|
||||
"timestamp" : "0x55d9c571",
|
||||
"transactionsTrie" : "5c9151c2413d1cd25c51ffb4ac38948acc1359bf08c6b49f283660e9bcf0f516",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"rlp" : "0xf90261f901f9a0e688d736f1307c6f97b6777381b30556137b9d4ca5c43fbd5b30d6b5df315264a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0cb52de543653d86ccd13ba3ddf8b052525b04231c6884a4db3188a184681d878a05c9151c2413d1cd25c51ffb4ac38948acc1359bf08c6b49f283660e9bcf0f516a0e9244cf7503b79c03d3a099e07a80d2dbc77bb0b502d8a89d51ac0d68dd31313b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd88252088455d9c57180a04296af28ea723598c959f1cabc6f01fa0c75d126cfde89f13ccd9debcf3079c3883213b3fd7789f5d5f862f86080018304cb2f94095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba077c7cd36820c71821c1aed59de46e70e701c4a8dd89c9ba508ab722210f60da8a03f29825d40c7c3f7bff3ca69267e0f3fb74b2d18b8c2c4e3c135b5d3b06e288dc0",
|
||||
"transactions" : [
|
||||
{
|
||||
"data" : "0x",
|
||||
"gasLimit" : "0x04cb2f",
|
||||
"gasPrice" : "0x01",
|
||||
"nonce" : "0x00",
|
||||
"r" : "0x77c7cd36820c71821c1aed59de46e70e701c4a8dd89c9ba508ab722210f60da8",
|
||||
"s" : "0x3f29825d40c7c3f7bff3ca69267e0f3fb74b2d18b8c2c4e3c135b5d3b06e288d",
|
||||
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
|
||||
"v" : "0x1b",
|
||||
"value" : "0x0a"
|
||||
}
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020040",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefd8",
|
||||
"gasUsed" : "0x5208",
|
||||
"hash" : "04e0807bea4d9766809afba8f4dbf2e5ab4e522aa4570bb915381c6593530e89",
|
||||
"mixHash" : "782e9bf4a3427dee8cf2494f966830dd04a217eb5cf8769dba0ed6400212264f",
|
||||
"nonce" : "e83b4878a0b9a46f",
|
||||
"number" : "0x02",
|
||||
"parentHash" : "19c900975f94fd78dc12ad13740200fbe0a2eba43fd070bedc65588b0c95438a",
|
||||
"receiptTrie" : "5ea1a8b24652fed0ecab4738edd9211891eb8c4353c345973b78a02cc0f32f6b",
|
||||
"stateRoot" : "e7e4760f75476ec7f51869d8bdce5c693058fd5a95c77ea9c0bf7ced1e50d70e",
|
||||
"timestamp" : "0x55d9c573",
|
||||
"transactionsTrie" : "c673e076264c4669a5c2e479f1757b78e42511efe33b5fd2c0a23b929c7f87f5",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"rlp" : "0xf90260f901f9a019c900975f94fd78dc12ad13740200fbe0a2eba43fd070bedc65588b0c95438aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0e7e4760f75476ec7f51869d8bdce5c693058fd5a95c77ea9c0bf7ced1e50d70ea0c673e076264c4669a5c2e479f1757b78e42511efe33b5fd2c0a23b929c7f87f5a05ea1a8b24652fed0ecab4738edd9211891eb8c4353c345973b78a02cc0f32f6bb90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302004002832fefd88252088455d9c57380a0782e9bf4a3427dee8cf2494f966830dd04a217eb5cf8769dba0ed6400212264f88e83b4878a0b9a46ff861f85f01018304cb2f94095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba033c86e64d708c97c6b135cadff79dbf45985aa0b53694789e90d15f756765f239f1d0f8caa2a16405148c9d85581be5814960010f3cba938b5501590cea1f7cfc0",
|
||||
"transactions" : [
|
||||
{
|
||||
"data" : "0x",
|
||||
"gasLimit" : "0x04cb2f",
|
||||
"gasPrice" : "0x01",
|
||||
"nonce" : "0x01",
|
||||
"r" : "0x33c86e64d708c97c6b135cadff79dbf45985aa0b53694789e90d15f756765f23",
|
||||
"s" : "0x1d0f8caa2a16405148c9d85581be5814960010f3cba938b5501590cea1f7cf",
|
||||
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
|
||||
"v" : "0x1b",
|
||||
"value" : "0x0a"
|
||||
}
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
]
|
||||
},
|
||||
{
|
||||
"blockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020080",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefd8",
|
||||
"gasUsed" : "0x5208",
|
||||
"hash" : "eed1b4da708283370856fc76352d68f36d9766b7f366da372e2992ced9a1f663",
|
||||
"mixHash" : "c250fe02a675a64e068023f48df2662ff2269d970f7689bde287228e200d5401",
|
||||
"nonce" : "105781dacf8bcf41",
|
||||
"number" : "0x03",
|
||||
"parentHash" : "04e0807bea4d9766809afba8f4dbf2e5ab4e522aa4570bb915381c6593530e89",
|
||||
"receiptTrie" : "4ede0225773c7a517b91994aca65ade45124e7ef4b8be1e6097c9773a11920af",
|
||||
"stateRoot" : "e9940294a09308406a3d2e09203aed11db40259fac0a25e639ad2b30b82d07de",
|
||||
"timestamp" : "0x55d9c577",
|
||||
"transactionsTrie" : "1722b8a91bfc4f5614ce36ee77c7cce6620ab4af36d3c54baa66d7dbeb7bce1a",
|
||||
"uncleHash" : "1e8797b712282d23d059df15e9082411499795fe2644bdfb35f310c10c78169b"
|
||||
},
|
||||
"rlp" : "0xf90479f901f9a004e0807bea4d9766809afba8f4dbf2e5ab4e522aa4570bb915381c6593530e89a01e8797b712282d23d059df15e9082411499795fe2644bdfb35f310c10c78169b948888f1f195afa192cfee860698584c030f4c9db1a0e9940294a09308406a3d2e09203aed11db40259fac0a25e639ad2b30b82d07dea01722b8a91bfc4f5614ce36ee77c7cce6620ab4af36d3c54baa66d7dbeb7bce1aa04ede0225773c7a517b91994aca65ade45124e7ef4b8be1e6097c9773a11920afb90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefd88252088455d9c57780a0c250fe02a675a64e068023f48df2662ff2269d970f7689bde287228e200d540188105781dacf8bcf41f862f86002018304cb2f94095e7baea6a6c7c4c2dfeb977efac326af552d870a801ca015eb1cc916728b9799e55c489857727669afb2986433d5f54cde11faaed9f0eea05d36f6d06c34aae8d0a2a5895c8ba4a17ad46a5fa59f361cb3e7e01a23030e38f90216f90213a019c900975f94fd78dc12ad13740200fbe0a2eba43fd070bedc65588b0c95438aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794bcde5374fce5edbc8e2a8697c15331677e6ebf0ba0cb52de543653d86ccd13ba3ddf8b052525b04231c6884a4db3188a184681d878a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000002832fefd880a0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80a06868c784ca472bb16eb9b23029965a737713003d0da6c006e4923e400cd783fc88d99c24fcd2648302",
|
||||
"transactions" : [
|
||||
{
|
||||
"data" : "0x",
|
||||
"gasLimit" : "0x04cb2f",
|
||||
"gasPrice" : "0x01",
|
||||
"nonce" : "0x02",
|
||||
"r" : "0x15eb1cc916728b9799e55c489857727669afb2986433d5f54cde11faaed9f0ee",
|
||||
"s" : "0x5d36f6d06c34aae8d0a2a5895c8ba4a17ad46a5fa59f361cb3e7e01a23030e38",
|
||||
"to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87",
|
||||
"v" : "0x1c",
|
||||
"value" : "0x0a"
|
||||
}
|
||||
],
|
||||
"uncleHeaders" : [
|
||||
{
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "bcde5374fce5edbc8e2a8697c15331677e6ebf0b",
|
||||
"difficulty" : "0x020000",
|
||||
"extraData" : "0x",
|
||||
"gasLimit" : "0x2fefd8",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "5264110fedc6f468e9b3c1fead10ee4bdd4957bcb6d193503f8ede6a0d478b95",
|
||||
"mixHash" : "6868c784ca472bb16eb9b23029965a737713003d0da6c006e4923e400cd783fc",
|
||||
"nonce" : "d99c24fcd2648302",
|
||||
"number" : "0x02",
|
||||
"parentHash" : "19c900975f94fd78dc12ad13740200fbe0a2eba43fd070bedc65588b0c95438a",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "cb52de543653d86ccd13ba3ddf8b052525b04231c6884a4db3188a184681d878",
|
||||
"timestamp" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"genesisBlockHeader" : {
|
||||
"bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
|
||||
"coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1",
|
||||
"difficulty" : "0x020000",
|
||||
"extraData" : "0x42",
|
||||
"gasLimit" : "0x2fefd8",
|
||||
"gasUsed" : "0x00",
|
||||
"hash" : "e688d736f1307c6f97b6777381b30556137b9d4ca5c43fbd5b30d6b5df315264",
|
||||
"mixHash" : "f35b4695bdfef02db19d255636bec7911667c7056df2b2f475053ea78dd1b0ff",
|
||||
"nonce" : "5333c47f947590d8",
|
||||
"number" : "0x00",
|
||||
"parentHash" : "0000000000000000000000000000000000000000000000000000000000000000",
|
||||
"receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"stateRoot" : "7dba07d6b448a186e9612e5f737d1c909dce473e53199901a302c00646d523c1",
|
||||
"timestamp" : "0x54c98c81",
|
||||
"transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
|
||||
"uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"
|
||||
},
|
||||
"genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a07dba07d6b448a186e9612e5f737d1c909dce473e53199901a302c00646d523c1a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808454c98c8142a0f35b4695bdfef02db19d255636bec7911667c7056df2b2f475053ea78dd1b0ff885333c47f947590d8c0c0",
|
||||
"lastblockhash" : "eed1b4da708283370856fc76352d68f36d9766b7f366da372e2992ced9a1f663",
|
||||
"postState" : {
|
||||
"095e7baea6a6c7c4c2dfeb977efac326af552d87" : {
|
||||
"balance" : "0x14",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
},
|
||||
"8888f1f195afa192cfee860698584c030f4c9db1" : {
|
||||
"balance" : "0x8ac7230489e8a410",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
},
|
||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x09184e71fbdc",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x02",
|
||||
"storage" : {
|
||||
}
|
||||
}
|
||||
},
|
||||
"pre" : {
|
||||
"a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : {
|
||||
"balance" : "0x09184e72a000",
|
||||
"code" : "0x",
|
||||
"nonce" : "0x00",
|
||||
"storage" : {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -131,12 +131,12 @@ type Env struct {
|
||||
initial bool
|
||||
Gas *big.Int
|
||||
|
||||
origin common.Address
|
||||
parent common.Hash
|
||||
origin common.Address
|
||||
//parent common.Hash
|
||||
coinbase common.Address
|
||||
|
||||
number *big.Int
|
||||
time *big.Int
|
||||
time uint64
|
||||
difficulty *big.Int
|
||||
gasLimit *big.Int
|
||||
|
||||
@ -163,10 +163,10 @@ func NewEnvFromMap(state *state.StateDB, envValues map[string]string, exeValues
|
||||
env := NewEnv(state)
|
||||
|
||||
env.origin = common.HexToAddress(exeValues["caller"])
|
||||
env.parent = common.HexToHash(envValues["previousHash"])
|
||||
//env.parent = common.Hex2Bytes(envValues["previousHash"])
|
||||
env.coinbase = common.HexToAddress(envValues["currentCoinbase"])
|
||||
env.number = common.Big(envValues["currentNumber"])
|
||||
env.time = common.Big(envValues["currentTimestamp"])
|
||||
env.time = common.Big(envValues["currentTimestamp"]).Uint64()
|
||||
env.difficulty = common.Big(envValues["currentDifficulty"])
|
||||
env.gasLimit = common.Big(envValues["currentGasLimit"])
|
||||
env.Gas = new(big.Int)
|
||||
@ -174,10 +174,12 @@ func NewEnvFromMap(state *state.StateDB, envValues map[string]string, exeValues
|
||||
return env
|
||||
}
|
||||
|
||||
func (self *Env) Origin() common.Address { return self.origin }
|
||||
func (self *Env) BlockNumber() *big.Int { return self.number }
|
||||
func (self *Env) Origin() common.Address { return self.origin }
|
||||
func (self *Env) BlockNumber() *big.Int { return self.number }
|
||||
|
||||
//func (self *Env) PrevHash() []byte { return self.parent }
|
||||
func (self *Env) Coinbase() common.Address { return self.coinbase }
|
||||
func (self *Env) Time() *big.Int { return self.time }
|
||||
func (self *Env) Time() uint64 { return self.time }
|
||||
func (self *Env) Difficulty() *big.Int { return self.difficulty }
|
||||
func (self *Env) State() *state.StateDB { return self.state }
|
||||
func (self *Env) GasLimit() *big.Int { return self.gasLimit }
|
||||
|
@ -19,7 +19,6 @@ package xeth
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strings"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
@ -77,7 +76,7 @@ type Block struct {
|
||||
Hash string `json:"hash"`
|
||||
Transactions *common.List `json:"transactions"`
|
||||
Uncles *common.List `json:"uncles"`
|
||||
Time *big.Int `json:"time"`
|
||||
Time uint64 `json:"time"`
|
||||
Coinbase string `json:"coinbase"`
|
||||
Name string `json:"name"`
|
||||
GasLimit string `json:"gasLimit"`
|
||||
|
30
xeth/xeth.go
30
xeth/xeth.go
@ -20,10 +20,8 @@ package xeth
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"regexp"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -47,7 +45,6 @@ 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
|
||||
@ -126,7 +123,7 @@ func New(ethereum *eth.Ethereum, frontend Frontend) *XEth {
|
||||
if frontend == nil {
|
||||
xeth.frontend = dummyFrontend{}
|
||||
}
|
||||
xeth.state = NewState(xeth, xeth.backend.ChainManager().State())
|
||||
xeth.state = NewState(xeth, xeth.backend.ChainManager().TransState())
|
||||
|
||||
go xeth.start()
|
||||
go xeth.filterManager.Start()
|
||||
@ -313,12 +310,7 @@ func (self *XEth) EthTransactionByHash(hash string) (tx *types.Transaction, blha
|
||||
// some chain, this probably needs to be refactored for more expressiveness
|
||||
data, _ := self.backend.ExtraDb().Get(common.FromHex(hash))
|
||||
if len(data) != 0 {
|
||||
dtx := new(types.Transaction)
|
||||
if err := rlp.DecodeBytes(data, dtx); err != nil {
|
||||
glog.V(logger.Error).Infoln(err)
|
||||
return
|
||||
}
|
||||
tx = dtx
|
||||
tx = types.NewTransactionFromBytes(data)
|
||||
} else { // check pending transactions
|
||||
tx = self.backend.TxPool().GetTransaction(common.HexToHash(hash))
|
||||
}
|
||||
@ -781,14 +773,8 @@ func (self *XEth) FromNumber(str string) string {
|
||||
}
|
||||
|
||||
func (self *XEth) PushTx(encodedTx string) (string, error) {
|
||||
tx := new(types.Transaction)
|
||||
err := rlp.DecodeBytes(common.FromHex(encodedTx), tx)
|
||||
if err != nil {
|
||||
glog.V(logger.Error).Infoln(err)
|
||||
return "", err
|
||||
}
|
||||
|
||||
err = self.backend.TxPool().Add(tx)
|
||||
tx := types.NewTransactionFromBytes(common.FromHex(encodedTx))
|
||||
err := self.backend.TxPool().Add(tx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -881,10 +867,6 @@ 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)
|
||||
@ -894,10 +876,6 @@ 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)
|
||||
|
@ -1,26 +0,0 @@
|
||||
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")
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user