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

eth/63 fast synchronization algorithm #1889

Merged
merged 11 commits into from
Oct 21, 2015
3 changes: 1 addition & 2 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
utils.DataDirFlag,
utils.BlockchainVersionFlag,
utils.OlympicFlag,
utils.EthVersionFlag,
utils.FastSyncFlag,
utils.CacheFlag,
utils.JSpathFlag,
utils.ListenPortFlag,
Expand Down Expand Up @@ -360,7 +360,6 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
utils.SetupLogger(ctx)
utils.SetupNetwork(ctx)
utils.SetupVM(ctx)
utils.SetupEth(ctx)
if ctx.GlobalBool(utils.PProfEanbledFlag.Name) {
utils.StartPProf(ctx)
}
Expand Down
23 changes: 5 additions & 18 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,9 @@ var (
Name: "olympic",
Usage: "Use olympic style protocol",
}
EthVersionFlag = cli.IntFlag{
Name: "eth",
Value: 62,
Usage: "Highest eth protocol to advertise (temporary, dev option)",
FastSyncFlag = cli.BoolFlag{
Name: "fast",
Usage: "Enables fast syncing through state downloads",
}

// miner settings
Expand Down Expand Up @@ -425,12 +424,13 @@ 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")
}

// Assemble the entire eth configuration and return
cfg := &eth.Config{
Name: common.MakeName(clientID, version),
DataDir: MustDataDir(ctx),
GenesisNonce: ctx.GlobalInt(GenesisNonceFlag.Name),
GenesisFile: ctx.GlobalString(GenesisFileFlag.Name),
FastSync: ctx.GlobalBool(FastSyncFlag.Name),
BlockChainVersion: ctx.GlobalInt(BlockchainVersionFlag.Name),
DatabaseCache: ctx.GlobalInt(CacheFlag.Name),
SkipBcVersionCheck: false,
Expand Down Expand Up @@ -499,7 +499,6 @@ func MakeEthConfig(clientID, version string, ctx *cli.Context) *eth.Config {

glog.V(logger.Info).Infoln("dev mode enabled")
}

return cfg
}

Expand Down Expand Up @@ -532,18 +531,6 @@ func SetupVM(ctx *cli.Context) {
vm.SetJITCacheSize(ctx.GlobalInt(VMJitCacheFlag.Name))
}

// SetupEth configures the eth packages global settings
func SetupEth(ctx *cli.Context) {
version := ctx.GlobalInt(EthVersionFlag.Name)
for len(eth.ProtocolVersions) > 0 && eth.ProtocolVersions[0] > uint(version) {
eth.ProtocolVersions = eth.ProtocolVersions[1:]
eth.ProtocolLengths = eth.ProtocolLengths[1:]
}
if len(eth.ProtocolVersions) == 0 {
Fatalf("No valid eth protocols remaining")
}
}

// MakeChain creates a chain manager from set command line flags.
func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database) {
datadir := MustDataDir(ctx)
Expand Down
2 changes: 1 addition & 1 deletion core/bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
// Generate a chain of b.N blocks using the supplied block
// generator function.
genesis := WriteGenesisBlockForTesting(db, GenesisAccount{benchRootAddr, benchRootFunds})
chain := GenerateChain(genesis, db, b.N, gen)
chain, _ := GenerateChain(genesis, db, b.N, gen)

// Time the insertion of the new chain.
// State and blocks are stored in the same DB.
Expand Down
44 changes: 34 additions & 10 deletions core/block_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func (self *BlockProcessor) ApplyTransaction(gp GasPool, statedb *state.StateDB,
}

logs := statedb.GetLogs(tx.Hash())
receipt.SetLogs(logs)
receipt.Logs = logs
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})

glog.V(logger.Debug).Infoln(receipt)
Expand Down Expand Up @@ -195,14 +195,16 @@ func (sm *BlockProcessor) Process(block *types.Block) (logs vm.Logs, receipts ty
defer sm.mutex.Unlock()

if sm.bc.HasBlock(block.Hash()) {
return nil, nil, &KnownBlockError{block.Number(), block.Hash()}
if _, err := state.New(block.Root(), sm.chainDb); err == nil {
return nil, nil, &KnownBlockError{block.Number(), block.Hash()}
}
}

if !sm.bc.HasBlock(block.ParentHash()) {
return nil, nil, ParentError(block.ParentHash())
if parent := sm.bc.GetBlock(block.ParentHash()); parent != nil {
if _, err := state.New(parent.Root(), sm.chainDb); err == nil {
return sm.processWithParent(block, parent)
}
}
parent := sm.bc.GetBlock(block.ParentHash())
return sm.processWithParent(block, parent)
return nil, nil, ParentError(block.ParentHash())
}

func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs vm.Logs, receipts types.Receipts, err error) {
Expand Down Expand Up @@ -364,18 +366,40 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs vm.Logs, err error)
receipts := GetBlockReceipts(sm.chainDb, block.Hash())
// coalesce logs
for _, receipt := range receipts {
logs = append(logs, receipt.Logs()...)
logs = append(logs, receipt.Logs...)
}
return logs, nil
}

// ValidateHeader verifies the validity of a header, relying on the database and
// POW behind the block processor.
func (sm *BlockProcessor) ValidateHeader(header *types.Header, checkPow, uncle bool) error {
// Short circuit if the header's already known or its parent missing
if sm.bc.HasHeader(header.Hash()) {
return nil
}
if parent := sm.bc.GetHeader(header.ParentHash); parent == nil {
return ParentError(header.ParentHash)
} else {
return ValidateHeader(sm.Pow, header, parent, checkPow, uncle)
}
}

// ValidateHeaderWithParent verifies the validity of a header, relying on the database and
// POW behind the block processor.
func (sm *BlockProcessor) ValidateHeaderWithParent(header, parent *types.Header, checkPow, uncle bool) error {
if sm.bc.HasHeader(header.Hash()) {
return nil
}
return ValidateHeader(sm.Pow, header, parent, checkPow, uncle)
}

// See YP section 4.3.4. "Block Header Validity"
// Validates a header. Returns an error if the header is invalid.
func ValidateHeader(pow pow.PoW, header *types.Header, parent *types.Header, checkPow, uncle bool) error {
if big.NewInt(int64(len(header.Extra))).Cmp(params.MaximumExtraDataSize) == 1 {
return fmt.Errorf("Header extra data too long (%d)", len(header.Extra))
}

if uncle {
if header.Time.Cmp(common.MaxBig) == 1 {
return BlockTSTooBigErr
Expand Down Expand Up @@ -412,7 +436,7 @@ func ValidateHeader(pow pow.PoW, header *types.Header, parent *types.Header, che
if checkPow {
// Verify the nonce of the header. Return an error if it's not valid
if !pow.Verify(types.NewBlockWithHeader(header)) {
return ValidationError("Header's nonce is invalid (= %x)", header.Nonce)
return &BlockNonceErr{Hash: header.Hash(), Number: header.Number, Nonce: header.Nonce.Uint64()}
}
}
return nil
Expand Down
20 changes: 10 additions & 10 deletions core/block_processor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,16 @@ func TestPutReceipt(t *testing.T) {
hash[0] = 2

receipt := new(types.Receipt)
receipt.SetLogs(vm.Logs{&vm.Log{
Address: addr,
Topics: []common.Hash{hash},
Data: []byte("hi"),
Number: 42,
TxHash: hash,
TxIndex: 0,
BlockHash: hash,
Index: 0,
}})
receipt.Logs = vm.Logs{&vm.Log{
Address: addr,
Topics: []common.Hash{hash},
Data: []byte("hi"),
BlockNumber: 42,
TxHash: hash,
TxIndex: 0,
BlockHash: hash,
Index: 0,
}}

PutReceipts(db, types.Receipts{receipt})
receipt = GetReceipt(db, common.Hash{})
Expand Down
Loading