mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-13 15:33:47 +00:00
Merge branch 'ethereum:master' into gethintegration
This commit is contained in:
commit
92d07bc432
4 changed files with 56 additions and 23 deletions
|
|
@ -84,19 +84,20 @@ type execStats struct {
|
||||||
|
|
||||||
func timedExec(bench bool, execFunc func() ([]byte, uint64, error)) ([]byte, execStats, error) {
|
func timedExec(bench bool, execFunc func() ([]byte, uint64, error)) ([]byte, execStats, error) {
|
||||||
if bench {
|
if bench {
|
||||||
|
testing.Init()
|
||||||
// Do one warm-up run
|
// Do one warm-up run
|
||||||
output, gasUsed, err := execFunc()
|
output, gasUsed, err := execFunc()
|
||||||
result := testing.Benchmark(func(b *testing.B) {
|
result := testing.Benchmark(func(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
haveOutput, haveGasUsed, haveErr := execFunc()
|
haveOutput, haveGasUsed, haveErr := execFunc()
|
||||||
if !bytes.Equal(haveOutput, output) {
|
if !bytes.Equal(haveOutput, output) {
|
||||||
b.Fatalf("output differs, have\n%x\nwant%x\n", haveOutput, output)
|
panic(fmt.Sprintf("output differs\nhave %x\nwant %x\n", haveOutput, output))
|
||||||
}
|
}
|
||||||
if haveGasUsed != gasUsed {
|
if haveGasUsed != gasUsed {
|
||||||
b.Fatalf("gas differs, have %v want%v", haveGasUsed, gasUsed)
|
panic(fmt.Sprintf("gas differs, have %v want %v", haveGasUsed, gasUsed))
|
||||||
}
|
}
|
||||||
if haveErr != err {
|
if haveErr != err {
|
||||||
b.Fatalf("err differs, have %v want%v", haveErr, err)
|
panic(fmt.Sprintf("err differs, have %v want %v", haveErr, err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -137,7 +138,7 @@ func runCmd(ctx *cli.Context) error {
|
||||||
var (
|
var (
|
||||||
tracer *tracing.Hooks
|
tracer *tracing.Hooks
|
||||||
debugLogger *logger.StructLogger
|
debugLogger *logger.StructLogger
|
||||||
statedb *state.StateDB
|
prestate *state.StateDB
|
||||||
chainConfig *params.ChainConfig
|
chainConfig *params.ChainConfig
|
||||||
sender = common.BytesToAddress([]byte("sender"))
|
sender = common.BytesToAddress([]byte("sender"))
|
||||||
receiver = common.BytesToAddress([]byte("receiver"))
|
receiver = common.BytesToAddress([]byte("receiver"))
|
||||||
|
|
@ -174,7 +175,7 @@ func runCmd(ctx *cli.Context) error {
|
||||||
defer triedb.Close()
|
defer triedb.Close()
|
||||||
genesis := genesisConfig.MustCommit(db, triedb)
|
genesis := genesisConfig.MustCommit(db, triedb)
|
||||||
sdb := state.NewDatabase(triedb, nil)
|
sdb := state.NewDatabase(triedb, nil)
|
||||||
statedb, _ = state.New(genesis.Root(), sdb)
|
prestate, _ = state.New(genesis.Root(), sdb)
|
||||||
chainConfig = genesisConfig.Config
|
chainConfig = genesisConfig.Config
|
||||||
|
|
||||||
if ctx.String(SenderFlag.Name) != "" {
|
if ctx.String(SenderFlag.Name) != "" {
|
||||||
|
|
@ -231,7 +232,7 @@ func runCmd(ctx *cli.Context) error {
|
||||||
}
|
}
|
||||||
runtimeConfig := runtime.Config{
|
runtimeConfig := runtime.Config{
|
||||||
Origin: sender,
|
Origin: sender,
|
||||||
State: statedb,
|
State: prestate,
|
||||||
GasLimit: initialGas,
|
GasLimit: initialGas,
|
||||||
GasPrice: flags.GlobalBig(ctx, PriceFlag.Name),
|
GasPrice: flags.GlobalBig(ctx, PriceFlag.Name),
|
||||||
Value: flags.GlobalBig(ctx, ValueFlag.Name),
|
Value: flags.GlobalBig(ctx, ValueFlag.Name),
|
||||||
|
|
@ -274,14 +275,18 @@ func runCmd(ctx *cli.Context) error {
|
||||||
if ctx.Bool(CreateFlag.Name) {
|
if ctx.Bool(CreateFlag.Name) {
|
||||||
input = append(code, input...)
|
input = append(code, input...)
|
||||||
execFunc = func() ([]byte, uint64, error) {
|
execFunc = func() ([]byte, uint64, error) {
|
||||||
|
// don't mutate the state!
|
||||||
|
runtimeConfig.State = prestate.Copy()
|
||||||
output, _, gasLeft, err := runtime.Create(input, &runtimeConfig)
|
output, _, gasLeft, err := runtime.Create(input, &runtimeConfig)
|
||||||
return output, gasLeft, err
|
return output, gasLeft, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if len(code) > 0 {
|
if len(code) > 0 {
|
||||||
statedb.SetCode(receiver, code)
|
prestate.SetCode(receiver, code)
|
||||||
}
|
}
|
||||||
execFunc = func() ([]byte, uint64, error) {
|
execFunc = func() ([]byte, uint64, error) {
|
||||||
|
// don't mutate the state!
|
||||||
|
runtimeConfig.State = prestate.Copy()
|
||||||
output, gasLeft, err := runtime.Call(receiver, input, &runtimeConfig)
|
output, gasLeft, err := runtime.Call(receiver, input, &runtimeConfig)
|
||||||
return output, initialGas - gasLeft, err
|
return output, initialGas - gasLeft, err
|
||||||
}
|
}
|
||||||
|
|
@ -291,7 +296,7 @@ func runCmd(ctx *cli.Context) error {
|
||||||
output, stats, err := timedExec(bench, execFunc)
|
output, stats, err := timedExec(bench, execFunc)
|
||||||
|
|
||||||
if ctx.Bool(DumpFlag.Name) {
|
if ctx.Bool(DumpFlag.Name) {
|
||||||
root, err := statedb.Commit(genesisConfig.Number, true)
|
root, err := runtimeConfig.State.Commit(genesisConfig.Number, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to commit changes %v\n", err)
|
fmt.Printf("Failed to commit changes %v\n", err)
|
||||||
return err
|
return err
|
||||||
|
|
@ -310,7 +315,7 @@ func runCmd(ctx *cli.Context) error {
|
||||||
logger.WriteTrace(os.Stderr, debugLogger.StructLogs())
|
logger.WriteTrace(os.Stderr, debugLogger.StructLogs())
|
||||||
}
|
}
|
||||||
fmt.Fprintln(os.Stderr, "#### LOGS ####")
|
fmt.Fprintln(os.Stderr, "#### LOGS ####")
|
||||||
logger.WriteLogs(os.Stderr, statedb.Logs())
|
logger.WriteLogs(os.Stderr, runtimeConfig.State.Logs())
|
||||||
}
|
}
|
||||||
|
|
||||||
if bench || ctx.Bool(StatDumpFlag.Name) {
|
if bench || ctx.Bool(StatDumpFlag.Name) {
|
||||||
|
|
|
||||||
|
|
@ -277,6 +277,13 @@ func (bc *BlockChain) GetTransactionLookup(hash common.Hash) (*rawdb.LegacyTxLoo
|
||||||
if tx == nil {
|
if tx == nil {
|
||||||
progress, err := bc.TxIndexProgress()
|
progress, err := bc.TxIndexProgress()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// No error is returned if the transaction indexing progress is unreachable
|
||||||
|
// due to unexpected internal errors. In such cases, it is impossible to
|
||||||
|
// determine whether the transaction does not exist or has simply not been
|
||||||
|
// indexed yet without a progress marker.
|
||||||
|
//
|
||||||
|
// In such scenarios, the transaction is treated as unreachable, though
|
||||||
|
// this is clearly an unintended and unexpected situation.
|
||||||
return nil, nil, nil
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
// The transaction indexing is not finished yet, returning an
|
// The transaction indexing is not finished yet, returning an
|
||||||
|
|
|
||||||
|
|
@ -206,24 +206,47 @@ func New(config Config, diskdb ethdb.KeyValueStore, triedb *triedb.Database, roo
|
||||||
log.Warn("Snapshot maintenance disabled (syncing)")
|
log.Warn("Snapshot maintenance disabled (syncing)")
|
||||||
return snap, nil
|
return snap, nil
|
||||||
}
|
}
|
||||||
|
// Create the building waiter iff the background generation is allowed
|
||||||
|
if !config.NoBuild && !config.AsyncBuild {
|
||||||
|
defer snap.waitBuild()
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn("Failed to load snapshot", "err", err)
|
log.Warn("Failed to load snapshot", "err", err)
|
||||||
if config.NoBuild {
|
if !config.NoBuild {
|
||||||
return nil, err
|
snap.Rebuild(root)
|
||||||
|
return snap, nil
|
||||||
}
|
}
|
||||||
wait := snap.Rebuild(root)
|
return nil, err // Bail out the error, don't rebuild automatically.
|
||||||
if !config.AsyncBuild {
|
|
||||||
wait()
|
|
||||||
}
|
|
||||||
return snap, nil
|
|
||||||
}
|
}
|
||||||
// Existing snapshot loaded, seed all the layers
|
// Existing snapshot loaded, seed all the layers
|
||||||
for ; head != nil; head = head.Parent() {
|
for head != nil {
|
||||||
snap.layers[head.Root()] = head
|
snap.layers[head.Root()] = head
|
||||||
|
head = head.Parent()
|
||||||
}
|
}
|
||||||
return snap, nil
|
return snap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// waitBuild blocks until the snapshot finishes rebuilding. This method is meant
|
||||||
|
// to be used by tests to ensure we're testing what we believe we are.
|
||||||
|
func (t *Tree) waitBuild() {
|
||||||
|
// Find the rebuild termination channel
|
||||||
|
var done chan struct{}
|
||||||
|
|
||||||
|
t.lock.RLock()
|
||||||
|
for _, layer := range t.layers {
|
||||||
|
if layer, ok := layer.(*diskLayer); ok {
|
||||||
|
done = layer.genPending
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.lock.RUnlock()
|
||||||
|
|
||||||
|
// Wait until the snapshot is generated
|
||||||
|
if done != nil {
|
||||||
|
<-done
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Disable interrupts any pending snapshot generator, deletes all the snapshot
|
// Disable interrupts any pending snapshot generator, deletes all the snapshot
|
||||||
// layers in memory and marks snapshots disabled globally. In order to resume
|
// layers in memory and marks snapshots disabled globally. In order to resume
|
||||||
// the snapshot functionality, the caller must invoke Rebuild.
|
// the snapshot functionality, the caller must invoke Rebuild.
|
||||||
|
|
@ -665,9 +688,8 @@ func (t *Tree) Journal(root common.Hash) (common.Hash, error) {
|
||||||
|
|
||||||
// Rebuild wipes all available snapshot data from the persistent database and
|
// Rebuild wipes all available snapshot data from the persistent database and
|
||||||
// discard all caches and diff layers. Afterwards, it starts a new snapshot
|
// discard all caches and diff layers. Afterwards, it starts a new snapshot
|
||||||
// generator with the given root hash. The returned function blocks until
|
// generator with the given root hash.
|
||||||
// regeneration is complete.
|
func (t *Tree) Rebuild(root common.Hash) {
|
||||||
func (t *Tree) Rebuild(root common.Hash) (wait func()) {
|
|
||||||
t.lock.Lock()
|
t.lock.Lock()
|
||||||
defer t.lock.Unlock()
|
defer t.lock.Unlock()
|
||||||
|
|
||||||
|
|
@ -699,11 +721,9 @@ func (t *Tree) Rebuild(root common.Hash) (wait func()) {
|
||||||
// Start generating a new snapshot from scratch on a background thread. The
|
// Start generating a new snapshot from scratch on a background thread. The
|
||||||
// generator will run a wiper first if there's not one running right now.
|
// generator will run a wiper first if there's not one running right now.
|
||||||
log.Info("Rebuilding state snapshot")
|
log.Info("Rebuilding state snapshot")
|
||||||
disk := generateSnapshot(t.diskdb, t.triedb, t.config.CacheSize, root)
|
|
||||||
t.layers = map[common.Hash]snapshot{
|
t.layers = map[common.Hash]snapshot{
|
||||||
root: disk,
|
root: generateSnapshot(t.diskdb, t.triedb, t.config.CacheSize, root),
|
||||||
}
|
}
|
||||||
return func() { <-disk.genPending }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AccountIterator creates a new account iterator for the specified root hash and
|
// AccountIterator creates a new account iterator for the specified root hash and
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ type StateDB interface {
|
||||||
GetBalance(common.Address) *uint256.Int
|
GetBalance(common.Address) *uint256.Int
|
||||||
GetNonce(common.Address) uint64
|
GetNonce(common.Address) uint64
|
||||||
GetCode(common.Address) []byte
|
GetCode(common.Address) []byte
|
||||||
|
GetCodeHash(common.Address) common.Hash
|
||||||
GetState(common.Address, common.Hash) common.Hash
|
GetState(common.Address, common.Hash) common.Hash
|
||||||
GetTransientState(common.Address, common.Hash) common.Hash
|
GetTransientState(common.Address, common.Hash) common.Hash
|
||||||
Exist(common.Address) bool
|
Exist(common.Address) bool
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue