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

Implement ldb database functionality for optional addr index. #11

Merged
merged 1 commit into from
Jan 26, 2015

Conversation

Roasbeef
Copy link
Member

This pull request alters the btcdb.db interface, adding new functions for accessing/updating/deleting the optional address index. For now, only the ldb driver implements the newly defined functions. memdb has also been altered, but only to supply skeleton functions in order for the package to conform to the new btcdb interface (won't compile otherwise). Additionally this PR makes progress towards completion of btcsuite/btcd#190. Subsequent PR's dependant upon this one will be opened across: btcd + btcjson + btcrpcclient, ultimately fully implementing btcd's new optional addrindex.

In order to provide functionality for storage of a new address-based transaction index, the following functions have been added to the btcdb, Db interface:

  type Db interface {
      ....
      FetchAddrIndexTip() (sha *btcwire.ShaHash, height int64, err error)
      UpdateAddrIndexForBlock(blkSha *btcwire.ShaHash, blkHeight int64, addrIndex *BlockAddrIndex) error
      FetchTxsForAddr(addr *btcutil.Address, skip int, limit int) ([]*TxListReply, error)
      DeleteAddrIndex() error
  }

Along with a helper type-def:

  • type BlockAddrIndex map[[ripemd160.Size]byte][]*btcwire.TxLoc

A single entry in the new optional index takes up 38-bytes raw, and is layed out like the following:

       ----------------------------------------------------------------------
       | Prefix  | Hash160  | BlkHeight | Tx Offset | Tx Size |
       ----------------------------------------------------------------------
       | 2 bytes | 20 bytes |  8 bytes  |  4 bytes  | 4 bytes |
       ----------------------------------------------------------------------

Each index maps a hash160 to a transaction locator object (offset and size within block). Indexes are stored purely in the key (leaving blank bytes for the value), to make it easy to seek and limit the number of transactions returned via iterators. An ability to skip and limit the number of returned transactions is also required to properly implement the searchrawtransaction RPC.

@coveralls
Copy link

Coverage Status

Coverage increased (+2.18%) when pulling 34c7350 on Roasbeef:addrindex into b2186ae on conformal:master.

@davecgh
Copy link
Member

davecgh commented Dec 25, 2014

I don't expect btcwire will need to be touched.

@Roasbeef
Copy link
Member Author

Ah, you're right! My mistake, updated current PR description to reflect this.

@Roasbeef Roasbeef changed the title [WIP - DO NOT MERGE] Implement ldb database functionality for optional addr index. Implement ldb database functionality for optional addr index. Jan 4, 2015
@davecgh
Copy link
Member

davecgh commented Jan 19, 2015

Can you rebase this and update it for all the new paths please?

// transaction which is commited before the function returns.
// Addresses are indexed by the raw bytes of their base58 decoded
// hash160.
UpdateAddrIndexForBlock(blkSha *btcwire.ShaHash, blkHeight int64,
Copy link
Member

Choose a reason for hiding this comment

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

Minor nit, but the rest of the parameters are called height int64, should probably be consistent.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed.

@coveralls
Copy link

Coverage Status

Coverage increased (+2.18%) when pulling 080fdb5 on Roasbeef:addrindex into c67a305 on btcsuite:master.

@davecgh
Copy link
Member

davecgh commented Jan 20, 2015

@jrick is going to also review this. With the latest changes, it's looking pretty good for me. I'll give it another round of review in a bit.

)

// Errors that the various database functions may return.
var (
ErrAddrIndexDoesNotExist = errors.New("Address index hasn't been built up yet.")
Copy link
Member

Choose a reason for hiding this comment

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

Don't use capitals and punctuation in error strings.

golint should catch this but for some reason the travis build still succeeded.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed.


data, err := db.lDb.Get(addrIndexMetaDataKey, db.ro)
if err != nil {
return &btcwire.ShaHash{}, -1, btcdb.ErrAddrIndexDoesNotExist
Copy link
Member

Choose a reason for hiding this comment

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

This answers my question above.. but why not return nil here instead? Otherwise we end up creating additional garbage for no good reason, for a value that shouldn't be touched to begin with.

Copy link
Member Author

Choose a reason for hiding this comment

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

Very good point, returning nil instead does seem to be better behavior. It currently returns a pointer to the btcwire zero hash simply to emulate the behavior of NewestSha, for sake of consistency.

If changed to return nil, then following the same logic, should we also change NewestSha and update all callers the react to the new behavior? I think that'd require changes in both btcd and btcchain, and maybe some other packages I can't name off-head.

Copy link
Member

Choose a reason for hiding this comment

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

Hmm true, I didn't realize NewestSha behaved the same way. I think it should be changed, but with the existing db interface being rewritten anyways, I wouldn't worry too much about it.

@jrick
Copy link
Member

jrick commented Jan 20, 2015

I think I would prefer having the address index methods on a "greater" interface then the existing db. Then, instead of needing to add noop methods to other database drivers (memdb for example) you can type assert your db variable against the interface to check for the existence of address index features.

So, something like this (in btcdb):

type AddressIndexDB interface {
    DB
    FetchAddrIndexTip() (sha *btcwire.ShaHash, height int32, err error)
    UpdateAddrIndexForBlock(blkSha *btcwire.ShaHash, height int32, addrIndex BlockAddrIndex) error
    // ...
}

And the caller:

switch db := db.(type) {
case btcdb.AddressIndexDB:
    // Call address index methods
default:
    // Address index not supported
}

// or...

adb, ok := db.(btcdb.AddressIndexDB)
if !ok {
    // not supported
}
// use address index methods from the adb instance

@davecgh
Copy link
Member

davecgh commented Jan 20, 2015

I think the idea for the AddressIndexDB interface makes sense for longer term, but since btcdb is in the process of being redone completely and this will no longer be an issue, is it worth doing it now?

@jrick
Copy link
Member

jrick commented Jan 20, 2015

Nah, but it's something to consider when the db interface is rewritten.

Any other optional features could be added in the same manner.

@coveralls
Copy link

Coverage Status

Coverage increased (+2.26%) when pulling ee94a3e on Roasbeef:addrindex into c67a305 on btcsuite:master.

@Roasbeef
Copy link
Member Author

Fixed another linter warning, the Travis build scripts seem to be allowing builds through that fail golint?

@coveralls
Copy link

Coverage Status

Coverage increased (+2.41%) to 65.51% when pulling 8d234ab on Roasbeef:addrindex into c67a305 on btcsuite:master.

@davecgh
Copy link
Member

davecgh commented Jan 26, 2015

Ok, I think this is set now. Can you rebase it and squash it down into a single commit (or at least a few commits which address specific functionality) as I like to avoid having a bunch of extra commits on master that are simply addressing review items, lint issues, etc.

@coveralls
Copy link

Coverage Status

Coverage increased (+2.41%) to 65.51% when pulling b284bf0 on Roasbeef:addrindex into c67a305 on btcsuite:master.

@Roasbeef
Copy link
Member Author

Rebased+squashed into a single commit.

@conformal-deploy conformal-deploy merged commit b284bf0 into btcsuite:master Jan 26, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants