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

tx/address indexing as optional feature, with separate db #475

Merged
merged 47 commits into from
Apr 13, 2018
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
a778e22
feat: create WIP prototype for tx/address indexing
whilei Jan 16, 2018
71c0b77
dep ensure
whilei Jan 18, 2018
d87a807
init batching sketch
whilei Jan 18, 2018
ffaed6a
use delegated batching for atxi cmd
whilei Jan 18, 2018
3a39d4c
dep ensure: remove progress bar deps
whilei Jan 19, 2018
031c198
Rename AddTxIndexesBatch->WriteBlockAddrTxIndexesBatch
whilei Jan 19, 2018
63f5c83
write atxis for bc insertreceipts and reorg
whilei Jan 19, 2018
4b45f42
remove atxis given bc rollback or reorg
whilei Jan 19, 2018
e09bd1a
improvements based on @tzdybal feedback
whilei Jan 19, 2018
0fd5868
rename toOrFromOrBoth -> direction
whilei Jan 19, 2018
ec6f4e6
compare uint64s blockstart/stopNs instead of converting to bigints
whilei Jan 19, 2018
674da81
simplify t/f direction check for iterator
whilei Jan 19, 2018
cd429f7
rename more toOrFrom -> direction
whilei Jan 19, 2018
0c746d3
refactor putBlockAddrTxsToBatch and atxi-build cmd
whilei Jan 19, 2018
0c38d84
Add comments and remove unused fn
whilei Jan 19, 2018
67769f6
a few minor tweaks and improvements, comments, etc
whilei Jan 19, 2018
4fc155f
move atxi placeholder to db k/v, polish cmd ui
whilei Jan 19, 2018
74d7fe0
write test for atxi, refactor, and fix bu
whilei Jan 20, 2018
cdb4055
test for fast/full sync implements atxi if enabled
whilei Jan 20, 2018
2ef0157
problem: atxi not removing indexes
whilei Jan 21, 2018
258d418
problem: weirdly named signature var for tx Diff fn
whilei Jan 21, 2018
2644af4
problem: duplicate txs hashes return when chain reorg
whilei Jan 21, 2018
4bb36a1
problem: no tests for atxi rm or reorg
whilei Jan 21, 2018
429d2ab
allow empty tx.to to allow querying just contracts
whilei Jan 21, 2018
bf00bf0
minor refactorings for code cleanliness, see pr code comments
whilei Jan 21, 2018
a7dbbb5
solution: implement addition param for standard/contract filter
whilei Jan 21, 2018
8f36212
problem: nix pointer on contract tx type putting atxi
whilei Jan 21, 2018
0ba44ce
problem: don't skip atxi for to==nil txs
whilei Jan 21, 2018
cb4ed85
problem: unhandled index db allowance
whilei Jan 21, 2018
55a7eff
problem: no formatter for web3ext input formatter
whilei Jan 22, 2018
5807140
Merge branch 'master' into feat/addr-tx-index-proto
whilei Mar 4, 2018
f2eb1ba
problem: api should use human-friendly t|f|tf/ft interface
whilei Mar 4, 2018
e4f15d2
Merge master and resolve conflicts
whilei Apr 5, 2018
513ad88
solution: remove redundant horizontal rule from usage output
whilei Apr 5, 2018
02efe7f
gofmt: project-wide
whilei Apr 5, 2018
a29921a
problem: merge missed atxi command/flag additions
whilei Apr 5, 2018
54773f6
solution: add comment to explain cache ratio sharing
whilei Apr 5, 2018
f5adee2
problem: unused addr.IsEmpty func
whilei Apr 5, 2018
e465063
problem: (refactor syntax) ugly 'removals' name collision
whilei Apr 5, 2018
4837014
solution: optimize key slice with known length
whilei Apr 5, 2018
42bf795
solution: merge to addr check conditional for eloquence
whilei Apr 5, 2018
95f000f
solution: add comment explaining atxi db cache ratio for sync (vs build)
whilei Apr 5, 2018
32505e2
problem: some addresses have lots of txs
whilei Apr 5, 2018
d69ac3b
problem: must ensure atxis are ordered by block number
whilei Apr 5, 2018
6ac5a9a
solution: fix variable shadowing and empty slice by struct init
whilei Apr 5, 2018
efc2a42
problem: atxis returned are backward
whilei Apr 5, 2018
2ec2a97
solution: move API debug_ -> geth_
whilei Apr 11, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 55 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

77 changes: 77 additions & 0 deletions cmd/geth/build_atxi_cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package main

import (
"gopkg.in/urfave/cli.v1"
"strconv"
"github.com/ethereumproject/go-ethereum/logger/glog"
"github.com/ethereumproject/go-ethereum/core/types"
"path/filepath"
"io/ioutil"
"os"
"github.com/ethereumproject/go-ethereum/logger"
"time"
)

func buildAddrTxIndexCmd(ctx *cli.Context) error {
startIndex := uint64(ctx.Int("start"))
var stopIndex uint64

// Use persistent placeholder in case start not spec'd
placeholderFilename := filepath.Join(MustMakeChainDataDir(ctx), "index.at")
if !ctx.IsSet("start") {
bs, err := ioutil.ReadFile(placeholderFilename)
if err == nil { // ignore errors for now
startIndex, _ = strconv.ParseUint(string(bs), 10, 64)
}
}

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

stopIndex = uint64(ctx.Int("stop"))
if stopIndex == 0 {
stopIndex = bc.CurrentHeader().Number.Uint64()
}

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

indexDb := MakeIndexDatabase(ctx)
if indexDb == nil {
panic("indexdb is nil")
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't you use glog.Fatal?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep.

}
defer indexDb.Close()

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

var inc = uint64(ctx.Int("step"))
startTime := time.Now()
glog.D(logger.Error).Infoln("Address/tx indexing (atxi) start:", startIndex, "stop:", stopIndex, "step:", inc)
for i := startIndex; i <= stopIndex; i = i+inc {
if i+inc > stopIndex {
inc = stopIndex - startIndex
}
if err := bc.AddTxIndexesBatch(indexDb, i, i+inc); err != nil {
return err
}
ioutil.WriteFile(placeholderFilename, []byte(strconv.Itoa(int(i+inc))), os.ModePerm)
}
ioutil.WriteFile(placeholderFilename, []byte(strconv.Itoa(int(stopIndex))), os.ModePerm)
glog.D(logger.Error).Infoln("Finished atxi. Took:", time.Since(startTime))
return nil
}


43 changes: 29 additions & 14 deletions cmd/geth/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -599,16 +599,17 @@ func mustMakeEthConf(ctx *cli.Context, sconf *core.SufficientChainConfig) *eth.C
}

ethConf := &eth.Config{
ChainConfig: sconf.ChainConfig,
Genesis: sconf.Genesis,
FastSync: ctx.GlobalBool(aliasableName(FastSyncFlag.Name, ctx)),
BlockChainVersion: ctx.GlobalInt(aliasableName(BlockchainVersionFlag.Name, ctx)),
DatabaseCache: ctx.GlobalInt(aliasableName(CacheFlag.Name, ctx)),
DatabaseHandles: MakeDatabaseHandles(),
NetworkId: sconf.Network,
AccountManager: accman,
Etherbase: MakeEtherbase(accman, ctx),
MinerThreads: ctx.GlobalInt(aliasableName(MinerThreadsFlag.Name, ctx)),
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)),
DatabaseHandles: MakeDatabaseHandles(),
NetworkId: sconf.Network,
AccountManager: accman,
Etherbase: MakeEtherbase(accman, ctx),
MinerThreads: ctx.GlobalInt(aliasableName(MinerThreadsFlag.Name, ctx)),
NatSpec: ctx.GlobalBool(aliasableName(NatspecEnabledFlag.Name, ctx)),
DocRoot: ctx.GlobalString(aliasableName(DocRootFlag.Name, ctx)),
GasPrice: new(big.Int),
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 @@ -89,6 +89,10 @@ var (
Name: "light-kdf,lightkdf",
Usage: "Reduce key-derivation RAM & CPU usage at some expense of KDF strength",
}
AddrTxIndexFlag = cli.BoolFlag{
Name: "add-tx-index,atxi",
Usage: "Toggle indexes for transactions by address. Pre-existing chaindata can be indexed with command 'geth atxi-build'",
}
// Network Split settings
ETFChain = cli.BoolFlag{
Name: "etf",
Expand Down
31 changes: 31 additions & 0 deletions cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,36 @@ func makeCLIApp() (app *cli.App) {
The output of this command is supposed to be machine-readable.
`,
},
{
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 'geth build-atxi' 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. [default: 10000]",
Value: 10000,
},
},
},
{
Action: makeMLogDocumentation,
Name: "mdoc",
Expand Down Expand Up @@ -132,6 +162,7 @@ func makeCLIApp() (app *cli.App) {
ChainIdentityFlag,
BlockchainVersionFlag,
FastSyncFlag,
AddrTxIndexFlag,
CacheFlag,
LightKDFFlag,
JSpathFlag,
Expand Down
Loading