Skip to content
This repository has been archived by the owner on Oct 4, 2019. It is now read-only.

Commit

Permalink
Merge branch 'feat/addr-tx-index-proto'
Browse files Browse the repository at this point in the history
  • Loading branch information
whilei committed Apr 13, 2018
2 parents 7636bef + 2ec2a97 commit 480f90a
Show file tree
Hide file tree
Showing 45 changed files with 1,301 additions and 99 deletions.
4 changes: 2 additions & 2 deletions accounts/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ func (ac *addrCache) find(a Account) (Account, error) {
return matches[i], nil
}
}
if (a.Address == common.Address{}) {
if a.Address.IsEmpty() {
return Account{}, ErrNoMatch
}
}
Expand Down Expand Up @@ -239,7 +239,7 @@ func (ac *addrCache) scan() ([]Account, error) {
switch {
case err != nil:
glog.V(logger.Debug).Infof("can't decode key %s: %v", path, err)
case (keyJSON.Address == common.Address{}):
case keyJSON.Address.IsEmpty():
glog.V(logger.Debug).Infof("can't decode key %s: missing or zero address", path)
default:
addrs = append(addrs, Account{Address: keyJSON.Address, File: path})
Expand Down
4 changes: 2 additions & 2 deletions accounts/cachedb.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ func (cdb *cacheDB) find(a Account) (Account, error) {
return acc, e
}
// no other possible way
if (a.Address == common.Address{}) {
if a.Address.IsEmpty() {
return Account{}, ErrNoMatch
}
}
Expand Down Expand Up @@ -498,7 +498,7 @@ func processKeyFile(wg *sync.WaitGroup, path string, fi os.FileInfo, i int, numF
case err != nil:
glog.V(logger.Debug).Infof("(%v/%v) can't decode key %s: %v", i, numFiles, path, err)
errs <- err
case (keyJSON.Address == common.Address{}):
case keyJSON.Address.IsEmpty():
glog.V(logger.Debug).Infof("(%v/%v) can't decode key %s: missing or zero address", i, numFiles, path)
errs <- fmt.Errorf("(%v/%v) can't decode key %s: missing or zero address", i, numFiles, path)
default:
Expand Down
146 changes: 146 additions & 0 deletions cmd/geth/build_atxi_cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package main

import (
"github.com/ethereumproject/go-ethereum/core"
"github.com/ethereumproject/go-ethereum/core/types"
"github.com/ethereumproject/go-ethereum/ethdb"
"github.com/ethereumproject/go-ethereum/logger"
"github.com/ethereumproject/go-ethereum/logger/glog"
"gopkg.in/urfave/cli.v1"
"os"
"time"
)

var buildAddrTxIndexCommand = cli.Command{
Action: buildAddrTxIndexCmd,
Name: "atxi-build",
Usage: "Generate index for transactions by address",
Description: `
Builds an index for transactions by address.
The command is idempotent; it will not hurt to run multiple times on the same range.
If run without --start flag, the command makes use of a persistent placeholder, so you can
run the command on multiple occasions and pick up indexing progress where the last session
left off.
To enable address-transaction indexing during block sync and import, use the '--atxi' flag.
`,
Flags: []cli.Flag{
cli.IntFlag{
Name: "start",
Usage: "Block number at which to begin building index",
},
cli.IntFlag{
Name: "stop",
Usage: "Block number at which to stop building index",
},
cli.IntFlag{
Name: "step",
Usage: "Step increment for batching. Higher number requires more mem, but may be faster",
Value: 10000,
},
},
}

func buildAddrTxIndexCmd(ctx *cli.Context) error {

// Divide global cache availability equally between chaindata (pre-existing blockdata) and
// address-transaction database. This ratio is arbitrary and could potentially be optimized or delegated to be user configurable.
ethdb.SetCacheRatio("chaindata", 0.5)
ethdb.SetHandleRatio("chaindata", 1)
ethdb.SetCacheRatio("indexes", 0.5)
ethdb.SetHandleRatio("indexes", 1)

startIndex := uint64(ctx.Int("start"))
var stopIndex uint64

indexDb := MakeIndexDatabase(ctx)
if indexDb == nil {
glog.Fatalln("indexes db is nil")
}
defer indexDb.Close()

// Use persistent placeholder in case start not spec'd
if !ctx.IsSet("start") {
startIndex = core.GetATXIBookmark(indexDb)
}

bc, chainDB := MakeChain(ctx)
if bc == nil || chainDB == nil {
glog.Fatalln("bc or cdb is nil")
}
defer chainDB.Close()

stopIndex = uint64(ctx.Int("stop"))
if stopIndex == 0 {
stopIndex = bc.CurrentBlock().NumberU64()
if n := bc.CurrentFastBlock().NumberU64(); n > stopIndex {
stopIndex = n
}
}

if stopIndex < startIndex {
glog.Fatalln("start must be prior to (smaller than) or equal to stop, got start=", startIndex, "stop=", stopIndex)
}
if startIndex == stopIndex {
glog.D(logger.Error).Infoln("atxi is up to date, exiting")
os.Exit(0)
}

var block *types.Block
blockIndex := startIndex
block = bc.GetBlockByNumber(blockIndex)
if block == nil {
glog.Fatalln(blockIndex, "block is nil")
}

var inc = uint64(ctx.Int("step"))
startTime := time.Now()
totalTxCount := uint64(0)
glog.D(logger.Error).Infoln("Address/tx indexing (atxi) start:", startIndex, "stop:", stopIndex, "step:", inc, "| This may take a while.")
breaker := false
for i := startIndex; i <= stopIndex; i = i + inc {
if i+inc > stopIndex {
inc = stopIndex - i
breaker = true
}

stepStartTime := time.Now()

// It may seem weird to pass i, i+inc, and inc, but its just a "coincidence"
// The function could accepts a smaller step for batch putting (in this case, inc),
// or a larger stopBlock (i+inc), but this is just how this cmd is using the fn now
// We could mess around a little with exploring batch optimization...
txsCount, err := bc.WriteBlockAddrTxIndexesBatch(indexDb, i, i+inc, inc)
if err != nil {
return err
}
totalTxCount += uint64(txsCount)

if err := core.SetATXIBookmark(indexDb, i+inc); err != nil {
glog.Fatalln(err)
}

glog.D(logger.Error).Infof("atxi-build: block %d / %d txs: %d took: %v %.2f bps %.2f txps", i+inc, stopIndex, txsCount, time.Since(stepStartTime).Round(time.Millisecond), float64(inc)/time.Since(stepStartTime).Seconds(), float64(txsCount)/time.Since(stepStartTime).Seconds())
glog.V(logger.Info).Infof("atxi-build: block %d / %d txs: %d took: %v %.2f bps %.2f txps", i+inc, stopIndex, txsCount, time.Since(stepStartTime).Round(time.Millisecond), float64(inc)/time.Since(stepStartTime).Seconds(), float64(txsCount)/time.Since(stepStartTime).Seconds())

if breaker {
break
}
}

if err := core.SetATXIBookmark(indexDb, stopIndex); err != nil {
glog.Fatalln(err)
}

// Print summary
totalBlocksF := float64(stopIndex - startIndex)
totalTxsF := float64(totalTxCount)
took := time.Since(startTime)
glog.D(logger.Error).Infof(`Finished atxi-build in %v: %d blocks (~ %.2f blocks/sec), %d txs (~ %.2f txs/sec)`,
took.Round(time.Second),
stopIndex-startIndex,
totalBlocksF/took.Seconds(),
totalTxCount,
totalTxsF/took.Seconds(),
)
return nil
}
23 changes: 19 additions & 4 deletions cmd/geth/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,7 @@ func mustMakeEthConf(ctx *cli.Context, sconf *core.SufficientChainConfig) *eth.C
ethConf := &eth.Config{
ChainConfig: sconf.ChainConfig,
Genesis: sconf.Genesis,
UseAddrTxIndex: ctx.GlobalBool(aliasableName(AddrTxIndexFlag.Name, ctx)),
FastSync: ctx.GlobalBool(aliasableName(FastSyncFlag.Name, ctx)),
BlockChainVersion: ctx.GlobalInt(aliasableName(BlockchainVersionFlag.Name, ctx)),
DatabaseCache: ctx.GlobalInt(aliasableName(CacheFlag.Name, ctx)),
Expand Down Expand Up @@ -799,18 +800,32 @@ func MustMakeChainConfigFromDefaults(ctx *cli.Context) *core.ChainConfig {
// MakeChainDatabase open an LevelDB using the flags passed to the client and will hard crash if it fails.
func MakeChainDatabase(ctx *cli.Context) ethdb.Database {
var (
datadir = MustMakeChainDataDir(ctx)
cache = ctx.GlobalInt(aliasableName(CacheFlag.Name, ctx))
handles = MakeDatabaseHandles()
chaindir = MustMakeChainDataDir(ctx)
cache = ctx.GlobalInt(aliasableName(CacheFlag.Name, ctx))
handles = MakeDatabaseHandles()
)

chainDb, err := ethdb.NewLDBDatabase(filepath.Join(datadir, "chaindata"), cache, handles)
chainDb, err := ethdb.NewLDBDatabase(filepath.Join(chaindir, "chaindata"), cache, handles)
if err != nil {
glog.Fatal("Could not open database: ", err)
}
return chainDb
}

func MakeIndexDatabase(ctx *cli.Context) ethdb.Database {
var (
chaindir = MustMakeChainDataDir(ctx)
cache = ctx.GlobalInt(aliasableName(CacheFlag.Name, ctx))
handles = MakeDatabaseHandles()
)

indexesDb, err := ethdb.NewLDBDatabase(filepath.Join(chaindir, "indexes"), cache, handles)
if err != nil {
glog.Fatal("Could not open database: ", err)
}
return indexesDb
}

// MakeChain creates a chain manager from set command line flags.
func MakeChain(ctx *cli.Context) (chain *core.BlockChain, chainDb ethdb.Database) {
var err error
Expand Down
4 changes: 4 additions & 0 deletions cmd/geth/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ var (
Name: "light-kdf,lightkdf",
Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
}
AddrTxIndexFlag = cli.BoolFlag{
Name: "atxi,add-tx-index",
Usage: "Toggle indexes for transactions by address. Pre-existing chaindata can be indexed with command 'atxi-build'",
}
// Network Split settings
ETFChain = cli.BoolFlag{
Name: "etf",
Expand Down
4 changes: 3 additions & 1 deletion cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ var makeDagCommand = cli.Command{
Usage: "Generate ethash dag (for testing)",
Description: `
The makedag command generates an ethash DAG in /tmp/dag.
This command exists to support the system testing project.
Regular users do not need to execute it.
`,
Expand Down Expand Up @@ -136,6 +136,7 @@ func makeCLIApp() (app *cli.App) {
gpuBenchCommand,
versionCommand,
makeMlogDocCommand,
buildAddrTxIndexCommand,
}

app.Flags = []cli.Flag{
Expand All @@ -153,6 +154,7 @@ func makeCLIApp() (app *cli.App) {
ChainIdentityFlag,
BlockchainVersionFlag,
FastSyncFlag,
AddrTxIndexFlag,
CacheFlag,
LightKDFFlag,
JSpathFlag,
Expand Down
13 changes: 7 additions & 6 deletions cmd/geth/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ import (
)

// AppHelpTemplate is the test template for the default, global app help topic.
//var x = cli.Command{}
//x.Usage
//x.UsageText
//x.ArgsUsage
//x.Subcommands
var AppHelpTemplate = `NAME:
{{.App.Name}} - {{.App.Usage}}
Expand All @@ -40,7 +35,7 @@ VERSION:
{{.App.Version}}{{if .CommandAndFlagGroups}}
COMMANDS AND FLAGS:
------------------------------------------------------------------------
{{range .CommandAndFlagGroups}}{{.Name}}
------------------------------------------------------------------------
{{if .Commands}}{{range .Commands}}
Expand Down Expand Up @@ -93,12 +88,14 @@ var AppHelpFlagAndCommandGroups = []flagGroup{
Commands: []cli.Command{
accountCommand,
walletCommand,
buildAddrTxIndexCommand,
},
Flags: []cli.Flag{
KeyStoreDirFlag,
UnlockedAccountFlag,
PasswordFileFlag,
AccountsIndexFlag,
AddrTxIndexFlag,
},
},
{
Expand Down Expand Up @@ -205,6 +202,10 @@ var AppHelpFlagAndCommandGroups = []flagGroup{
Flags: []cli.Flag{
WhisperEnabledFlag,
NatspecEnabledFlag,
DisplayFlag,
DisplayFormatFlag,
NeckbeardFlag,
AddrTxIndexFlag,
},
},
{
Expand Down
6 changes: 3 additions & 3 deletions common/registrar/registrar.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ func (self *Registrar) SetGlobalRegistrar(namereg string, addr common.Address) (
return
}
if zero.MatchString(GlobalRegistrarAddr) {
if (addr == common.Address{}) {
if addr.IsEmpty() {
err = fmt.Errorf("GlobalRegistrar address not found and sender for creation not given")
return
} else {
Expand Down Expand Up @@ -142,7 +142,7 @@ func (self *Registrar) SetHashReg(hashreg string, addr common.Address) (txhash s
HashRegAddr = "0x" + res[len(res)-40:]
}
if err != nil || zero.MatchString(HashRegAddr) {
if (addr == common.Address{}) {
if addr.IsEmpty() {
err = fmt.Errorf("HashReg address not found and sender for creation not given")
return
}
Expand Down Expand Up @@ -177,7 +177,7 @@ func (self *Registrar) SetUrlHint(urlhint string, addr common.Address) (txhash s
UrlHintAddr = "0x" + res[len(res)-40:]
}
if err != nil || zero.MatchString(UrlHintAddr) {
if (addr == common.Address{}) {
if addr.IsEmpty() {
err = fmt.Errorf("UrlHint address not found and sender for creation not given")
return
}
Expand Down
8 changes: 8 additions & 0 deletions common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,14 @@ func StringToAddress(s string) Address { return BytesToAddress([]byte(s)) }
func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) }
func HexToAddress(s string) Address { return BytesToAddress(FromHex(s)) }

func EmptyAddress(a Address) bool {
return a == Address{}
}

func (a Address) IsEmpty() bool {
return EmptyAddress(a)
}

// IsHexAddress verifies whether a string can represent a valid hex-encoded
// Ethereum address or not.
func IsHexAddress(s string) bool {
Expand Down
Loading

0 comments on commit 480f90a

Please sign in to comment.