Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Light client stage 1 #1684

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions cmd/evm/main.go
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/les/access"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
Expand Down Expand Up @@ -113,7 +114,7 @@ func run(ctx *cli.Context) {
glog.SetV(ctx.GlobalInt(VerbosityFlag.Name))

db, _ := ethdb.NewMemDatabase()
statedb, _ := state.New(common.Hash{}, db)
statedb, _ := state.New(common.Hash{}, access.NewDbChainAccess(db), access.NullCtx)
sender := statedb.CreateAccount(common.StringToAddress("sender"))
receiver := statedb.CreateAccount(common.StringToAddress("receiver"))
receiver.SetCode(common.Hex2Bytes(ctx.GlobalString(CodeFlag.Name)))
Expand Down Expand Up @@ -186,7 +187,7 @@ func NewEnv(state *state.StateDB, transactor common.Address, value *big.Int) *VM
}

func (self *VMEnv) Db() vm.Database { return self.state }
func (self *VMEnv) MakeSnapshot() vm.Database { return self.state.Copy() }
func (self *VMEnv) MakeSnapshot() vm.Database { return self.state.Copy(access.NullCtx) }
func (self *VMEnv) SetSnapshot(db vm.Database) { self.state.Set(db.(*state.StateDB)) }
func (self *VMEnv) Origin() common.Address { return *self.transactor }
func (self *VMEnv) BlockNumber() *big.Int { return common.Big0 }
Expand Down
3 changes: 2 additions & 1 deletion cmd/geth/blocktestcmd.go
Expand Up @@ -22,6 +22,7 @@ import (

"github.com/codegangsta/cli"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/les/access"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/tests"
Expand Down Expand Up @@ -124,7 +125,7 @@ func runOneBlockTest(ctx *cli.Context, test *tests.BlockTest) (*eth.Ethereum, er
if err != nil {
return ethereum, fmt.Errorf("Block Test load error: %v", err)
}
newDB, err := cm.State()
newDB, err := cm.State(access.NullCtx)
if err != nil {
return ethereum, fmt.Errorf("Block Test get state error: %v", err)
}
Expand Down
7 changes: 4 additions & 3 deletions cmd/geth/chaincmd.go
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/les/access"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
Expand Down Expand Up @@ -170,16 +171,16 @@ func dump(ctx *cli.Context) {
for _, arg := range ctx.Args() {
var block *types.Block
if hashish(arg) {
block = chain.GetBlock(common.HexToHash(arg))
block = chain.GetBlock(common.HexToHash(arg), access.NoOdr)
} else {
num, _ := strconv.Atoi(arg)
block = chain.GetBlockByNumber(uint64(num))
block = chain.GetBlockByNumber(uint64(num), access.NoOdr)
}
if block == nil {
fmt.Println("{}")
utils.Fatalf("block not found")
} else {
state, err := state.New(block.Root(), chainDb)
state, err := state.New(block.Root(), access.NewDbChainAccess(chainDb), access.NullCtx)
if err != nil {
utils.Fatalf("could not create new state: %v", err)
return
Expand Down
7 changes: 5 additions & 2 deletions cmd/geth/main.go
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/les/access"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
"github.com/ethereum/go-ethereum/ethdb"
Expand Down Expand Up @@ -304,6 +305,7 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
utils.BlockchainVersionFlag,
utils.OlympicFlag,
utils.FastSyncFlag,
utils.EthModeFlag,
utils.CacheFlag,
utils.JSpathFlag,
utils.ListenPortFlag,
Expand Down Expand Up @@ -554,12 +556,13 @@ func blockRecovery(ctx *cli.Context) {
if err != nil {
glog.Fatalln("could not open db:", err)
}
ca := access.NewDbChainAccess(blockDb)

var block *types.Block
if arg[0] == '#' {
block = core.GetBlock(blockDb, core.GetCanonicalHash(blockDb, common.String2Big(arg[1:]).Uint64()))
block = core.GetBlock(ca, core.GetCanonicalHash(blockDb, common.String2Big(arg[1:]).Uint64()), access.NoOdr)
} else {
block = core.GetBlock(blockDb, common.HexToHash(arg))
block = core.GetBlock(ca, common.HexToHash(arg), access.NoOdr)
}

if block == nil {
Expand Down
30 changes: 22 additions & 8 deletions cmd/utils/flags.go
Expand Up @@ -28,12 +28,14 @@ import (
"path/filepath"
"runtime"
"strconv"
"strings"

"github.com/codegangsta/cli"
"github.com/ethereum/ethash"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/les/access"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/eth"
Expand Down Expand Up @@ -133,11 +135,6 @@ var (
Name: "natspec",
Usage: "Enable NatSpec confirmation notice",
}
DocRootFlag = DirectoryFlag{
Name: "docroot",
Usage: "Document Root for HTTPClient file scheme",
Value: DirectoryString{common.HomeDir()},
}
CacheFlag = cli.IntFlag{
Name: "cache",
Usage: "Megabytes of memory allocated to internal caching (min 16MB / database forced)",
Expand All @@ -156,6 +153,11 @@ var (
Name: "lightkdf",
Usage: "Reduce KDF memory & CPU usage at some expense of KDF strength",
}
EthModeFlag = cli.StringFlag{
Name: "mode",
Value: "archive",
Usage: "Client mode of operation (archive, full, light)",
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This flag was dropped because it's too murky what it represents. Please rework the code so that it is based on a single --light flag. If it is passed, the cmd/geth/ package should initialize eth and les properly.

// Miner settings
// TODO: refactor CPU vs GPU mining flags
MiningEnabledFlag = cli.BoolFlag{
Expand Down Expand Up @@ -424,12 +426,25 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
if err != nil {
glog.V(logger.Error).Infoln("WARNING: No etherbase set and no accounts found as default")
}
// Resolve the mode of opeation from the string flag
var clientMode eth.Mode
switch strings.ToLower(ctx.GlobalString(EthModeFlag.Name)) {
case "archive":
clientMode = eth.ArchiveMode
case "full":
clientMode = eth.FullMode
case "light":
clientMode = eth.LightMode
default:
glog.Fatalf("Unknown node type requested: %s", ctx.GlobalString(EthModeFlag.Name))
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please drop these. They do not make sense in the context of the ETH protocol any more. The fast sync was already integrated separately as a bool flag. Why do you need to specify this mode to the eth package? If you are a light client, you should simply never even construct an eth object, so I don't see any rational behind modifying the eth.Config and the related things.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole backend is in eth, I definitely need that, I think duplicating the backend would be wrong. I just won't construct an eth ProtocolManager (I do agree about dropping NoSync, it was a bad idea). I can drop the mode flag and add a bool flag for light mode of course.

// Assemble the entire eth configuration and return
cfg := &eth.Config{
Name: common.MakeName(clientID, version),
DataDir: MustDataDir(ctx),
GenesisFile: ctx.GlobalString(GenesisFileFlag.Name),
FastSync: ctx.GlobalBool(FastSyncFlag.Name),
Mode: clientMode,
BlockChainVersion: ctx.GlobalInt(BlockchainVersionFlag.Name),
DatabaseCache: ctx.GlobalInt(CacheFlag.Name),
SkipBcVersionCheck: false,
Expand All @@ -446,7 +461,6 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {
Olympic: ctx.GlobalBool(OlympicFlag.Name),
NAT: MakeNAT(ctx),
NatSpec: ctx.GlobalBool(NatspecEnabledFlag.Name),
DocRoot: ctx.GlobalString(DocRootFlag.Name),
Discovery: !ctx.GlobalBool(NoDiscoverFlag.Name),
NodeKey: MakeNodeKey(ctx),
Shh: ctx.GlobalBool(WhisperEnabledFlag.Name),
Expand Down Expand Up @@ -552,12 +566,12 @@ func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database
eventMux := new(event.TypeMux)
pow := ethash.New()
//genesis := core.GenesisBlock(uint64(ctx.GlobalInt(GenesisNonceFlag.Name)), blockDB)
chain, err = core.NewBlockChain(chainDb, pow, eventMux)
chain, err = core.NewBlockChain(access.NewDbChainAccess(chainDb), pow, eventMux)
if err != nil {
Fatalf("Could not start chainmanager: %v", err)
}

proc := core.NewBlockProcessor(chainDb, pow, chain, eventMux)
proc := core.NewBlockProcessor(access.NewDbChainAccess(chainDb), pow, chain, eventMux)
chain.SetProcessor(proc)
return chain, chainDb
}
Expand Down
6 changes: 4 additions & 2 deletions core/bench_test.go
Expand Up @@ -24,6 +24,7 @@ import (
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/les/access"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
Expand Down Expand Up @@ -168,8 +169,9 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
// Time the insertion of the new chain.
// State and blocks are stored in the same DB.
evmux := new(event.TypeMux)
chainman, _ := NewBlockChain(db, FakePow{}, evmux)
chainman.SetProcessor(NewBlockProcessor(db, FakePow{}, chainman, evmux))
ca := access.NewDbChainAccess(db)
chainman, _ := NewBlockChain(ca, FakePow{}, evmux)
chainman.SetProcessor(NewBlockProcessor(ca, FakePow{}, chainman, evmux))
defer chainman.Stop()
b.ReportAllocs()
b.ResetTimer()
Expand Down
24 changes: 12 additions & 12 deletions core/block_processor.go
Expand Up @@ -23,11 +23,11 @@ import (
"time"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/les/access"
"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/crypto"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
Expand All @@ -43,7 +43,7 @@ const (
)

type BlockProcessor struct {
chainDb ethdb.Database
chainAccess *access.ChainAccess
// Mutex for locking the block processor. Blocks can only be handled one at a time
mutex sync.Mutex
// Canonical block chain
Expand Down Expand Up @@ -85,9 +85,9 @@ func (gp *GasPool) String() string {
return (*big.Int)(gp).String()
}

func NewBlockProcessor(db ethdb.Database, pow pow.PoW, blockchain *BlockChain, eventMux *event.TypeMux) *BlockProcessor {
func NewBlockProcessor(ca *access.ChainAccess, pow pow.PoW, blockchain *BlockChain, eventMux *event.TypeMux) *BlockProcessor {
sm := &BlockProcessor{
chainDb: db,
chainAccess: ca,
mem: make(map[string]*big.Int),
Pow: pow,
bc: blockchain,
Expand Down Expand Up @@ -189,7 +189,7 @@ func (sm *BlockProcessor) RetryProcess(block *types.Block) (logs vm.Logs, err er
if !sm.bc.HasBlock(block.ParentHash()) {
return nil, ParentError(block.ParentHash())
}
parent := sm.bc.GetBlock(block.ParentHash())
parent := sm.bc.GetBlock(block.ParentHash(), access.NoOdr)

// FIXME Change to full header validation. See #1225
errch := make(chan bool)
Expand All @@ -212,12 +212,12 @@ func (sm *BlockProcessor) Process(block *types.Block) (logs vm.Logs, receipts ty
defer sm.mutex.Unlock()

if sm.bc.HasBlock(block.Hash()) {
if _, err := state.New(block.Root(), sm.chainDb); err == nil {
if _, err := state.New(block.Root(), sm.chainAccess, access.NullCtx); err == nil {
return nil, nil, &KnownBlockError{block.Number(), block.Hash()}
}
}
if parent := sm.bc.GetBlock(block.ParentHash()); parent != nil {
if _, err := state.New(parent.Root(), sm.chainDb); err == nil {
if parent := sm.bc.GetBlock(block.ParentHash(), access.NoOdr); parent != nil {
if _, err := state.New(parent.Root(), sm.chainAccess, access.NullCtx); err == nil {
return sm.processWithParent(block, parent)
}
}
Expand All @@ -226,7 +226,7 @@ func (sm *BlockProcessor) Process(block *types.Block) (logs vm.Logs, receipts ty

func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs vm.Logs, receipts types.Receipts, err error) {
// Create a new state based on the parent's root (e.g., create copy)
state, err := state.New(parent.Root(), sm.chainDb)
state, err := state.New(parent.Root(), sm.chainAccess, access.NullCtx)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -369,8 +369,8 @@ func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *ty

// GetBlockReceipts returns the receipts beloniging to the block hash
func (sm *BlockProcessor) GetBlockReceipts(bhash common.Hash) types.Receipts {
if block := sm.BlockChain().GetBlock(bhash); block != nil {
return GetBlockReceipts(sm.chainDb, block.Hash())
if block := sm.BlockChain().GetBlock(bhash, access.NoOdr); block != nil {
return GetBlockReceipts(sm.chainAccess, block.Hash(), access.NoOdr)
}

return nil
Expand All @@ -380,7 +380,7 @@ func (sm *BlockProcessor) GetBlockReceipts(bhash common.Hash) types.Receipts {
// where it tries to get it from the (updated) method which gets them from the receipts or
// the depricated way by re-processing the block.
func (sm *BlockProcessor) GetLogs(block *types.Block) (logs vm.Logs, err error) {
receipts := GetBlockReceipts(sm.chainDb, block.Hash())
receipts := GetBlockReceipts(sm.chainAccess, block.Hash(), access.NoOdr)
// coalesce logs
for _, receipt := range receipts {
logs = append(logs, receipt.Logs...)
Expand Down
10 changes: 6 additions & 4 deletions core/block_processor_test.go
Expand Up @@ -22,6 +22,7 @@ import (
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/les/access"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
Expand All @@ -32,21 +33,22 @@ import (

func proc() (*BlockProcessor, *BlockChain) {
db, _ := ethdb.NewMemDatabase()
ca := access.NewDbChainAccess(db)
var mux event.TypeMux

WriteTestNetGenesisBlock(db, 0)
blockchain, err := NewBlockChain(db, thePow(), &mux)
blockchain, err := NewBlockChain(ca, thePow(), &mux)
if err != nil {
fmt.Println(err)
}
return NewBlockProcessor(db, ezp.New(), blockchain, &mux), blockchain
return NewBlockProcessor(ca, ezp.New(), blockchain, &mux), blockchain
}

func TestNumber(t *testing.T) {
pow := ezp.New()
_, chain := proc()

statedb, _ := state.New(chain.Genesis().Root(), chain.chainDb)
statedb, _ := state.New(chain.Genesis().Root(), access.NewDbChainAccess(chain.chainDb), access.NullCtx)
header := makeHeader(chain.Genesis(), statedb)
header.Number = big.NewInt(3)
err := ValidateHeader(pow, header, chain.Genesis().Header(), false, false)
Expand Down Expand Up @@ -82,7 +84,7 @@ func TestPutReceipt(t *testing.T) {
}}

PutReceipts(db, types.Receipts{receipt})
receipt = GetReceipt(db, common.Hash{})
receipt = GetReceipt(access.NewDbChainAccess(db), common.Hash{}, access.NoOdr)
if receipt == nil {
t.Error("expected to get 1 receipt, got none.")
}
Expand Down